De WikiSys
Aller à : navigation, rechercher

Intercepting requests and responses

HTTP Interception is a major feature of @angular/common/http.

With interception, you declare interceptors that inspect and transform HTTP requests from your application to the server.

The same interceptors may also inspect and transform the server's responses on their way back to the application.

Multiple interceptors form a forward-and-backward chain of request/response handlers.

Interceptors can perform a variety of implicit tasks, from authentication to logging, in a routine, standard way, for every HTTP request/response.

Without interception, developers would have to implement these tasks explicitly for each HttpClient method call.

Write an interceptor
import { Injectable } from '@angular/core';
import { HttpEvent, HttpInterceptor, HttpHandler, HttpRequest} from '@angular/common/http';
import { Observable } from 'rxjs';

/** Pass untouched request through to the next request handler. */

export class NoopInterceptor implements HttpInterceptor {

  intercept(req: HttpRequest<any>, next: HttpHandler):
    Observable<HttpEvent<any>> {
    return next.handle(req);

An Introduction to Angular HTTP Interceptors

Angular Authentication: Using the Http Client and Http Interceptors

Make an Authentication Service

When handling authentication in an Angular app, it’s generally best to put everything you need in a dedicated service. Any authentication service should have a few basic methods for allowing users to log in and log out. It should also include a method for retrieving a JSON Web Token from wherever it is stored on the client and a way to determine if the user is authenticated or not.

This article assumes you already have an authentication setup in place and that you are storing JWTs in local storage. We won’t get into a full details here.

One way we can check whether a JWT is expired is to use angular2-jwt to return a boolean after checking the exp claim.

npm i --save angular2-jwt

After installing angular2-jwt, use it in a service.

// src/app/auth/auth.service.tsimport { Injectable } from '@angular/core';
import decode from 'jwt-decode';


export class AuthService {  public getToken(): string {
    return localStorage.getItem('token');
  }  public isAuthenticated(): boolean {
    // get the token
    const token = this.getToken();
    // return a boolean reflecting 
    // whether or not the token is expired
    return tokenNotExpired(null, token);

Create an Interceptor

The goal is to include the JWT which is in local storage as the Authorization header in any HTTP request that is sent.

The first step is to create an interceptor.

To do this, create an Injectable class which implements HttpInterceptor.

// src/app/auth/token.interceptor.tsimport { Injectable } from '@angular/core';
import {
} from '@angular/common/http';

import { AuthService } from './auth/auth.service';
import { Observable } from 'rxjs/Observable';@Injectable()

export class TokenInterceptor implements HttpInterceptor {  constructor(public auth: AuthService) {}  

  intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
  newRequest = request.clone({
      setHeaders: {
        Authorization: `Bearer ${this.auth.getToken()}`
   return next.handle(newRequest);

Any interceptor that we want to create needs to implement the HttpInterceptor interface.

This means that our new class must have a method called intercept with HttpRequest and HttpHandler parameters.

Using interceptors is all about changing outgoing requests and incoming responses, but we can’t tamper with the original request–it needs to be immutable.

To make changes we need to clone the original request.

As we clone the original request we can set the headers we want. In our case its very simple–we just want to add an Authorization header with an auth scheme of Bearer followed by the JSON Web Token in local storage which we get from a call to the getToken method from the AuthService.

Calling next.handle means that we are passing control to the next interceptor in the chain, if there is one.

Add the Interceptor to Providers

The interceptor needs to be added to the HTTP_INTERCEPTORS array. This is done by making the existing HTTP_INTERCEPTORS array use the new class we’ve created.

Add this in the providers array for our application’s module.

// src/app/app.module.tsimport { HTTP_INTERCEPTORS } from '@angular/common/http';
import { TokenInterceptor } from './../auth/token.interceptor';@NgModule({
  bootstrap: [AppComponent],
  imports: [...],
  providers: [
      provide: HTTP_INTERCEPTORS,
      useClass: TokenInterceptor,
      multi: true
export class AppModule {}

Now when we make any HTTP request, the user’s token will be attached automatically.

// src/app/ping/ping.component.tsimport { HttpClient } from '@angular/common/http';
// ...
export class AppComponent {  constructor(public http: HttpClient) {}  public ping() {
        data => console.log(data),
        err => console.log(err)

This request will include an Authorization header with a value of Bearer ey....

It should be noted that Angular’s new HttpClient from @angular/common/http is being used here and not the Http class from @angular/http. If we try to make requests with the traditional Httpclass, the interceptor won’t be hit.

Looking for Unauthorized Responses

When tokens expire we will generally get a 401 Unauthorized response back from the server. This gives us an indication that we need the user to log in again to get a new token.

We have some choices to make at this point. Do we want to redirect to a specific route that has a login form? Do we want to show a modal? Do we want to attempt to refresh the token?

Either way, we need to set up the intereptor to handle responses. The intercept method returns an observable which means we can capture the success and error channels for a response and operate on them however we like. This is the perfect place to do any kind of logging we might want to do. We can also check for 401 Unauthorized responses and prompt the user to log in again.

// src/app/auth/jwt.interceptor.ts// ...
import 'rxjs/add/operator/do';

export class JwtInterceptor implements HttpInterceptor {  

   constructor(public auth: AuthService) {}  

   intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    return next.handle(request).do((event: HttpEvent<any>) => {
      if (event instanceof HttpResponse) {
        // do stuff with response if you want
    }, (err: any) => {
      if (err instanceof HttpErrorResponse) {
        if (err.status === 401) {
          // redirect to the login route
          // or show a modal

This is also a great spot to cache any failed requests. This comes in handy if we have token refreshing in place and we want to retry the requests once we have a new token.

// src/app/auth/auth.service.tsimport { HttpRequest } from '@angular/common/http';// ...
export class AuthService {cachedRequests: Array<HttpRequest<any>> = [];

public collectFailedRequest(request): void {
  }public retryFailedRequests(): void {
    // retry the requests. this method can
    // be called after the token is refreshed

The collectFailedRequests method can now be used in the interceptor.

// src/app/auth/jwt.interceptor.ts// ...

intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {    
  return next.handle(req).do((event: HttpEvent<any>) => {
    if (event instanceof HttpResponse) {
      // do stuff with response if you want
  }, (err: any) => {
    if (err instanceof HttpErrorResponse {
      if (err.status === 401) {

With this in place, we have the option of calling retryFailedRequests after the user’s token is refreshed to fire off the previously-failed requests. This is just a small addition that can help to greatly improve UX, especially if you have tokens with a very short lifetime. Wrapping Up

Angular 4.3 offers a brand new set of features for working with HTTP requests. Perhaps one of the most useful is the new HttpInterceptor interface which allows us to modify outgoing requests and incoming responses. This feature greatly simplifies a lot of previously tricky operations and removes the need for a lot of class wrappers that have been around since the early days of Angular 2.

In fact, a library that I wrote called angular2-jwt has, up until now, relied on wrapping all of the methods offered by Angular’s Http class. I’m now rewriting it to use HttpInterceptor and it is resulting in much less library code.

If you want to learn everything you need to know to properly secure an Angular application, be sure to check out the book that I’ll be launching this fall: Securing Angular Applications.