Búsqueda de sitios web

angular - Problema al configurar el encabezado usando HttpInterceptor


Tengo el siguiente código:

// config.service.ts
import { Injectable } from "@angular/core";

@Injectable()
export class ConfigService {
  private language: string = "en";
  constructor() {}
  set Language(lang: string) {
    this.language = lang;
  }
  get Language(): string {
    return this.language;
  }
}

// app.module.ts

import { BrowserModule } from "@angular/platform-browser";
import { NgModule, APP_INITIALIZER } from "@angular/core";

import { AppRoutingModule } from "./app-routing.module";
import { AppComponent } from "./app.component";

import { AnalyticsService, CoreModule, CrossDomainService } from "./core";
import { TileModule } from "./tile/tile.module";

@NgModule({
  declarations: [AppComponent],
  imports: [BrowserModule, AppRoutingModule, TileModule, CoreModule.forRoot()],
  providers: [
    {
      provide: APP_INITIALIZER,
      useFactory: onModuleInit,
      multi: true,
      deps: [CrossDomainService, AnalyticsService]
    }
  ],
  bootstrap: [AppComponent]
})
export class AppModule {}

export function onModuleInit(
  crossDomainService: CrossDomainService,
  analyticsService: AnalyticsService
) {
  return () => {
    console.log("App Init");
    crossDomainService.init();
    analyticsService.init();
    return new Promise(resolve => resolve(true));
  };
}

//core.module.ts
import { NgModule, ModuleWithProviders } from "@angular/core";
import { CommonModule } from "@angular/common";
import {
  HTTP_INTERCEPTORS,
  HttpClientModule,
  HttpClient
} from "@angular/common/http";

import { HttpRequestInterceptor } from "./http-request.interceptor";
import { ArticleService } from "./article.service";
import { CrossDomainService } from "./cross-domain.service";
import { AnalyticsService } from "./analytics.service";

import { TranslateModule, TranslateLoader } from "@ngx-translate/core";
import { TranslateHttpLoader } from "@ngx-translate/http-loader";
import { ConfigService } from "../config.service";

export function translateHttpLoaderFactory(http: HttpClient) {
  //return new TranslateHttpLoader(http);
  return new TranslateHttpLoader(http, "./assets/i18n/", ".json");
}

@NgModule({
  imports: [
    CommonModule,
    HttpClientModule,
    TranslateModule.forRoot({
      loader: {
        provide: TranslateLoader,
        useFactory: translateHttpLoaderFactory,
        deps: [HttpClient]
      }
    })
  ],
  providers: [
    ArticleService,
    CrossDomainService,
    AnalyticsService,
    {
      provide: HTTP_INTERCEPTORS,
      useClass: HttpRequestInterceptor,
      multi: true
    }
  ]
})
export class CoreModule {
  static forRoot(): ModuleWithProviders {
    return {
      ngModule: CoreModule,
      providers: [ConfigService]
    };
  }
}

//http-request.interceptor.ts
import { Injectable } from "@angular/core";
import {
  HttpEvent,
  HttpInterceptor,
  HttpHandler,
  HttpRequest
} from "@angular/common/http";
import { Observable } from "rxjs/Observable";
import { ConfigService } from "../config.service";

@Injectable()
export class HttpRequestInterceptor implements HttpInterceptor {
  language: string = "en";
   constructor(private config: ConfigService) {}

  intercept(
    req: HttpRequest<any>,
    next: HttpHandler
  ): Observable<HttpEvent<any>> {    
    const request = req.clone({
      setHeaders: { "Accept-Language": this.config.Language }
    });
    console.log(
      `Request header value : ${request.headers.get("Accept-Language")}`
    );

    return next.handle(request);
  }
}

CrossDomainService, en este caso se utiliza para obtener el idioma de un sistema externo. Es un conector entre la aplicación y los servicios externos.

El marco externo en este ejemplo va a suministrar el idioma a la aplicación Sample Angular. Supongamos que el valor inicial del idioma es 'en' y ahora si lo actualizamos a 'es', veo que HttpRequestInterceptor primero selecciona 'en' y luego 'es'. Entonces, todas las solicitudes de la API toman el valor del encabezado 'Accept-Language' como 'en' en lugar de 'es'. Si el marco externo está enviando el idioma 'fr', entonces en este caso veo que HttpRequestInterceptor primero selecciona 'es' y luego 'fr'. Por lo tanto, habrá algunas solicitudes de API que toman el valor del encabezado 'Accept-Language' como 'es' en lugar de 'fr'.

¿Alguien puede ayudarme a saber cómo solucionar este problema?

Respuesta #1

intenta reemplazar setheaders con headers así.

const request = req.clone({headers: req.headers.set('Accept-Language',this.config.Language)});

Respuesta #2

Sé que esta es una pregunta antigua, pero en caso de que alguien tenga problemas para configurar el encabezado 'Accept-Language' en todas las solicitudes en un interceptor, use esto:

request = request.clone({
  setHeaders: {
    'Accept-Language': this.config.Language + ';q=0.9,en-US,en;q=0.8'
  }
});

Esto funciona en Angular 11.2.