Angular 6 use Http Interceptor with config service

2019-07-30 22:40发布

问题:

I'm using Angular 6 and the issue is when I try to use an interceptor as an app module provider together with the APP_INITIALIZER to get the json config file from local.

My app module fragment is:

../src/app/app.module.ts (the providers fragment)

providers: [
  AppConfigService,
  {
    provide: APP_INITIALIZER,
    useFactory: initializeApp,
    deps: [AppConfigService], multi:  true
  },
  { provide: HTTP_INTERCEPTORS, useClass: TokenInterceptor, multi: true },
  { provide: LOCALE_ID, useValue: 'ES' },
  Title,
]

It's interesting that if I remove the interceptors, the code works well bringing the config file. My code to get the config file is:

../src/app/_services/app-config.service.ts

import { Injectable } from '@angular/core';
import { Response } from '@angular/http';
import { HttpClient } from '@angular/common/http';
import { environment } from '../../environments/environment.dev';
import { IAppConfig } from '../_models/_interfaces/app-config.model';

@Injectable()
export class AppConfigService {

static settings: IAppConfig;

constructor(private http: HttpClient) {}

load() {
    const jsonFile = `../../assets/config/config.${environment.name}.json`;
    return new Promise<void>((resolve, reject) => {
        this.http.get(jsonFile).toPromise().then((response: Response) => {
           AppConfigService.settings = <IAppConfig>response;
           resolve();
        }).catch((response: any) => {
           reject(`Could not load file '${jsonFile}': ${JSON.stringify(response)}`);
        });
    });
  }
}

Finally, the interceptor code:

../src/app/_interceptors/token.interceptor.ts

import {
  HttpRequest,
  HttpHandler,
  HttpEvent,
  HttpInterceptor
} from '@angular/common/http';
import { Observable } from 'rxjs/Observable';
import { AuthService } from '../_services/auth.service';

@Injectable()
export class TokenInterceptor implements HttpInterceptor {

  constructor(public auth: AuthService) {}

  intercept(request: HttpRequest<any>, next: HttpHandler): 
Observable<HttpEvent<any>> {

request = request.clone({
  setHeaders: {
    Authorization: `Bearer ${this.auth.getToken()}`
  }
});

return next.handle(request);

  }
}

When Angular compile the app it returns:

Could not load file '../../assets/config/config.dev.json': {}

I've tried several approaches trying to avoid this issue, but can't solve it until now.

Any tip about it?

Thanks in advance.

回答1:

When you are using HttpClient to get your configuration file, your interceptor is filtering that request as well. In your code the interceptor is replacing (not appending to existing) all the HTTP headers with Authorization header. When the default Content-Type application/json is lost, the request doesn't work anymore. Save and modify the old headers with request.headers.append(...) before setting them to cloned one.

OR

Define an exception for your file request in the interceptor. One simple way is to check which URL is used in request.url

if (request.url.indexOf('config') > -1) {
    requestModified = request.clone({
       url: request.url,
       headers: request.headers.set('Content-Type', 'application/json')
    });
}