Contents

Adding the same header on every request in Angular

Let me take a guess. You’re working on a new Angular project and you just figured out how to get an access token and included in a REST API request and it just worked. You were pumped up and excited but suddenly you realize that you now want that same token to be included on every request and still keep your code DRY. The problem is, you’re not 100% sure how to do it in Angular or perhaps you don’t know where to start. Well, you have come to the right blog post. Here I’ll show you not only how to do it easily, but also how to do it and look like a pro.

Interceptors

Let’s first talk about interceptors. Interceptors is not a new Angular concept. The interceptor pattern is actually a software design pattern that, when included in a framework, offers application developers the ability to change or add to a normal flow. It is sometimes also known as “middleware pattern”. This pattern can be applied to pretty much anything you’d like, including HTTP requests and responses. This allows you to place code as middleware that will be executed sometime between the time you make a call to a backend and the time the framework actually sends the request itself. This is the main reason that this pattern is called the interceptor pattern. It literally “intercepts” a remote call in order to do something with it right before it’s ready to leave the host.

Angular has included this software design pattern for HTTP requests/responses since a new HttpClient API was introduced in Angular 4.3.0 back in July 2017. Before then, Angular developers needed to do something else which is not going to be covered here since Angular 4 is no longer supported now. If you still use this older version of Angular, it is highly recommended that you upgrade it first.

In Angular, you’d not only need to declare and implement an HTTP Interceptor, but you’d also need to “provide it”. Let’s take a close look at each step and other potentially useful use cases for HTTP Interceptors.

Declare an HTTP Interceptor

Declaring an HTTP Interceptor in Angular is super easy with the Angular CLI. If you aren’t familiar with the Angular CLI, I highly recommend you not only take a look at it but master it. It is going to be your friend more often than not, so you’d better get along with it soon.

The Angular CLI to generate a new HTTP Interceptor may look like this:

ng g interceptor interceptors/add-headers

For more options, feel free to take a look at the official ng generate documentation for interceptors.

The above CLI command would yield the following boiler plate code:

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

@Injectable()
export class AddHeadersInterceptor implements HttpInterceptor {

  constructor() {}

  intercept(request: HttpRequest<unknown>, next: HttpHandler): Observable<HttpEvent<unknown>> {
    return next.handle(request);
  }
}

The way it is implemented by default would make no changes to whatever HTTP request you may make. However, it is ready for you to start making any changes you may need.

Notice there are two parameters declared for the intercept method. request will represent the request object that is about to be sent to a remote host. It is passed in to the intercept method so that we can take it as a starting point. Because this object is immutable, we cannot make changes directly to it. Instead, we will need to clone this object before we can change, remove, or add anything to the request object.

Next we have the next parameter. Pun is intended here. This object represents the next interceptor in the chain of interceptors. It is helpful to know that Angular already has this “interceptor” concept embedded in its HTTP requests flow. When you make a request to a backend with no interceptors of your own, the request would go through a chain of interceptors already implemented in Angular by default. When we add an interceptor of our own, we’re only adding it to the already existing chain of interceptors. The next object represents the next interceptor in the chain of interceptors, which could be some other interceptor we’ve added, or the next interceptor that Angular already has.

Calling next.handl() is required if you intend the request to continue. However, if for whatever reason you’d like to stop the request from continuing, you could technically skip calling next.handle(). If this is the case at some point, you would simply need to return your own Observable.

Implement an HTTP Interceptor

Your implementation will probably vary depending on where you store the access token or any specific business logic you may need. Generally, access tokens are stored in either the Local Storage or the Session Storage, making the retrieval of the token rather straight forward. Here I’ll provide an example of what that might look like and some line-by-line explanation of what’s going on:

1
2
3
4
5
  intercept(request: HttpRequest<unknown>, next: HttpHandler): Observable<HttpEvent<unknown>> {
    const newHeaders = request.headers.set('Authorization', 'your-access-token-goes-here');
    const newRequest = request.clone({ headers: newHeaders});
    return next.handle(newRequest);
  }
  • Line 2: This line creates a clone of the headers object based on the request.headers object plus the 'Authorization' header we’re including. According to the HttpHeaders.set documentation, if a header with the same name already exists in the original headers object, it will simply overwrite it.
  • Line 3: This line is creating a clone of the request object itself and sets the clone’s headers to the new headers created on line 2.
  • Line 4: Calls next.handle() but passes in the cloned request, following the immutability principle.

Provide an HTTP Interceptor

The term “provide” is an Angular term that is used to communicate the idea of letting Angular know about a service. You may have noticed that the AddHeadersInterceptor class generated by the Angular CLI in a previous step is actually decorated by the @Injectable() decorator. But, unlike a regular service, an interceptor must be provided using the HTTP_INTERCEPTORS multi-provider token. This is what it looks like in the providers array:

  providers: [
    { provide: HTTP_INTERCEPTORS, useClass: AddHeadersInterceptor, multi: true }
  ]

The import statement for the HTTP_INTERCEPTORS token is:

import { HTTP_INTERCEPTORS } from '@angular/common/http';

Conclusion

The above is the bear minimum you would need to get an HTTP interceptor going in Angular. HTTP Interceptors can also be used for other purposes such as showing a loader for every HTTP request, format conversion (XML to JSON, etc.), showing request status notifications and errors, profiling and logging, faking a backend, caching, and much more.

I hope this was as useful for you as it was for me.