Setting Default Headers in Angular
When building an Angular app, the chances are high that you’re going to need to set the same headers for most, if not all, of your service class’ API requests. In this post, I’m going to demonstrate how to set default headers both statically and dynamically. The examples below were done using Angular 4.0.0.
Setting Request Headers in a Service Class
For setting headers in a one-off request, we can just define headers as
RequestOptions and pass them as a argument to the http client’s function. Keep in
mind that you’ll need to import Headers and RequestOptions from @angular/http
into the service class.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
@Injectable()
export class WidgetService {
  updateWidget(widget: Widget): Observable<Widget> {
    const headers = new Headers({
      'Content-Type': 'application/vnd.api+json'
    });
    const options = new RequestOptions({
      headers: headers
    });
    return this.http
      .put(`widgets/${widget.id}`, widget, options)
      .map((response: Response) => {
        return response.json();
      });
  }
Having to do this for every request will get old real fast, not to metion leave you with 
repetitive code. Let’s see how to set the Content-Type header for all requests by default.
Setting Static Default Request Headers
To ensure that every request from the http client is configured with the same headers, we 
need to define a class to hold this configuration. Our class should be a subclass of 
BaseRequestOptions.  Then, in the constructor, we can set our headers.
1
2
3
4
5
6
7
@Injectable()
export class RequestOptionsService extends BaseRequestOptions {
  constructor() {
    super();
    this.headers.set('Content-Type', 'application/vnd.api+json');
  }
}
In the app.module we can tell Angular to use our custom class instead of 
the default RequestOptions.
1
2
3
providers: [
    { provide: RequestOptions, useClass: RequestOptionsService }
  ]
Setting the headers in this way means that the default headers are set when the Angular application starts up. In many cases this is just fine, but what if you need to set headers dynamically? Let’s take a look at how that can be done.
Setting Dynamic Default Request Headers
Let’s consider the following use case.  Our app needs to authenticate user requests using an
access token.  The user authenticates with their email and password and the API responds with
a JWT which our app stores in the browser’s localStorage. Each subsequent request must have
the JWT in the Authorization header.  The problem is that before we have added the JWT to
localStorage, the headers have already been set.  Our Authorization header might look like
this: "Authorization": "Beaer " - missing the JWT.  Another use case might involve setting a timestamp.
The solution is to override the merge function.  Every request merges options so we can define 
our dynamic headers there.
1
2
3
4
5
6
7
8
9
10
11
12
13
@Injectable()
export class RequestOptionsService extends BaseRequestOptions {
  constructor() {
    super();
    this.headers.set('Content-Type', 'application/vnd.api+json');
  }
  merge(options?: RequestOptionsArgs): RequestOptions {
    const newOptions = super.merge(options);
    newOptions.headers.set('Authorization',
                           `Beaer ${localStorage.getItem('app-token')}`);
    return newOptions;
  }
}