51

I try to use new Angular 4.3 interceptors for setting authorithation header for all requests. However, it is not working. I set breakpoint into the interceptors intercept method and browser did not hit it, so it seems like angular just ignores my interceptor. Please help me, thanks in advance.

user.service.ts:

import {Injectable} from '@angular/core';
import 'rxjs/add/operator/map';
import {Observable} from "rxjs";
import {Http} from "@angular/http";

@Injectable()
export class UserService {

  constructor(public http: Http) {
  }

  public getContacts(): Observable<any[]> {
    return this.http.get('/users/contacts').map(contacts => contacts.json());
  }
}

token.interceptor.ts

import {Injectable} from '@angular/core';
import {
  HttpRequest,
  HttpHandler,
  HttpEvent,
  HttpInterceptor
} from '@angular/common/http';
import {Observable} from 'rxjs/Observable';
import {AuthService} from "./shared/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);
  }
}

app.module.ts:

@NgModule({
  ...
  providers: [
    ...
    {provide: HTTP_INTERCEPTORS, useClass: TokenInterceptor, multi: true}
  ]
})
Matthew Green
  • 10,161
  • 4
  • 36
  • 54
Kirill Ivanov
  • 517
  • 1
  • 4
  • 6
  • will you be interested in a different approach like creating your own http service by extending a previous one. you can do the same there. – Gaurav Srivastava Jul 31 '17 at 14:24

3 Answers3

82

TL;DR Make sure there is one import of the HttpClientModule in the entire app (recommened) or provide valid interceptor configuration for each one (ofc for testing only).

Make sure that HttpClientModule is not imported multiple times across different modules of the app. I had it imported in lazy loaded modules. Each import creates a new copy of HttpClient using configuration from the module where it is imported, so interceptors provided in a root module are overwritten.

  • 9
    That's a pity there is no explanation about that in the angular docs. I imported HttpClientModule in my SharedModule, so the interceptor wasn't called in my lazy modules. Hopefully I found your answer, by **only** declaring HttpClientModule in my AppModule, everything workfs perfectly – Olivier Boissé Dec 18 '17 at 14:37
  • This makes me think why there is not a forRoot method in the HttpClientModule? –  Jan 23 '18 at 11:11
  • 1
    Okay, but if I'm using HttpClient in my nested component, how do I import it there? – Alex Shchur Feb 11 '18 at 15:42
  • @AlexeyShchur Export the HttpClientModule in your parent module. – Michał Chilczuk Feb 12 '18 at 09:41
76

The reason - you use old Http service instead of new service, introduced in Angular 4.3 - HttpClient (Http is going to be deprecated). Also, in the HttpClient JSON response type is assumed by default, so you should ommit .map(contacts => contacts.json()).

app.module.ts

...
import { HttpClientModule } from '@angular/common/http';

@NgModule({
 imports: [
   HttpClientModule,
   ...
 ],
 providers: [
   ...
   {provide: HTTP_INTERCEPTORS, useClass: TokenInterceptor, multi: true}
 ]
 ...
})

user.service.ts

...
import {HttpClient} from "@angular/common/http";

@Injectable()
export class UserService {

  constructor(public http: HttpClient) {
  }

  public getContacts(): Observable<any[]> {
    return this.http.get('/users/contacts');
  }
}
Maxim Kuzmin
  • 2,574
  • 19
  • 24
2

If you have already check that you are using the HttpClient service and you olny import HttpClientModule once but you still have problems check this:

If you are using providedIn: 'root' and your service is inside a module.

@Injectable({
  providedIn: 'root'
})
export class YourService {
    ...
}

Make sure that you haven't added the service in the providers array of your module.

@NgModule({
  ...
  providers: [
    YourService, // REMOVE THIS LINE
  ]
})
export class YourModule { }

That will overwrite your interceptors for that service.