[angular] Angular - Set headers for every request

I need to set some Authorization headers after the user has logged in, for every subsequent request.


To set headers for a particular request,

import {Headers} from 'angular2/http';
var headers = new Headers();
headers.append(headerName, value);

// HTTP POST using these headers
this.http.post(url, data, {
  headers: headers
})
// do something with the response

Reference

But it would be not be feasible to manually set request headers for every request in this way.

How do I set the headers set once the user has logged in, and also remove those headers on logout?

This question is related to angular

The answer is


How about Keeping a Separate Service like follows

            import {Injectable} from '@angular/core';
            import {Headers, Http, RequestOptions} from '@angular/http';


            @Injectable()
            export class HttpClientService extends RequestOptions {

                constructor(private requestOptionArgs:RequestOptions) {
                    super();     
                }

                addHeader(headerName: string, headerValue: string ){
                    (this.requestOptionArgs.headers as Headers).set(headerName, headerValue);
                }
            }

and when you calling this from another place use this.httpClientService.addHeader("Authorization", "Bearer " + this.tok);

and you will see the added header eg:- Authorization as follows

enter image description here


Although I'm answering it very late but it might help someone else. To inject headers to all requests when @NgModule is used, one can do the following:

(I tested this in Angular 2.0.1)

/**
 * Extending BaseRequestOptions to inject common headers to all requests.
 */
class CustomRequestOptions extends BaseRequestOptions {
    constructor() {
        super();
        this.headers.append('Authorization', 'my-token');
        this.headers.append('foo', 'bar');
    }
}

Now in @NgModule do the following:

@NgModule({
    declarations: [FooComponent],
    imports     : [

        // Angular modules
        BrowserModule,
        HttpModule,         // This is required

        /* other modules */
    ],
    providers   : [
        {provide: LocationStrategy, useClass: HashLocationStrategy},
        // This is the main part. We are telling Angular to provide an instance of
        // CustomRequestOptions whenever someone injects RequestOptions
        {provide: RequestOptions, useClass: CustomRequestOptions}
    ],
    bootstrap   : [AppComponent]
})

I like the idea to override default options, this seems like a good solution.

However, if you are up to extending the Http class. Make sure to read this through!

Some answers here are actually showing incorrect overloading of request() method, which could lead to a hard-to-catch errors and weird behavior. I've stumbled upon this myself.

This solution is based on request() method implementation in Angular 4.2.x, but should be future-compatible:

import {Observable} from 'rxjs/Observable';
import {Injectable} from '@angular/core';

import {
  ConnectionBackend, Headers,
  Http as NgHttp,
  Request,
  RequestOptions,
  RequestOptionsArgs,
  Response,
  XHRBackend
} from '@angular/http';


import {AuthenticationStateService} from '../authentication/authentication-state.service';


@Injectable()
export class Http extends NgHttp {

  constructor (
    backend: ConnectionBackend,
    defaultOptions: RequestOptions,
    private authenticationStateService: AuthenticationStateService
  ) {
    super(backend, defaultOptions);
  }


  request (url: string | Request, options?: RequestOptionsArgs): Observable<Response> {

    if ('string' === typeof url) {

      url = this.rewriteUrl(url);
      options = (options || new RequestOptions());
      options.headers = this.updateHeaders(options.headers);

      return super.request(url, options);

    } else if (url instanceof Request) {

      const request = url;
      request.url = this.rewriteUrl(request.url);
      request.headers = this.updateHeaders(request.headers);

      return super.request(request);

    } else {
      throw new Error('First argument must be a url string or Request instance');
    }

  }


  private rewriteUrl (url: string) {
    return environment.backendBaseUrl + url;
  }

  private updateHeaders (headers?: Headers) {

    headers = headers || new Headers();

    // Authenticating the request.
    if (this.authenticationStateService.isAuthenticated() && !headers.has('Authorization')) {
      headers.append('Authorization', 'Bearer ' + this.authenticationStateService.getToken());
    }

    return headers;

  }

}

Notice that I'm importing original class this way import { Http as NgHttp } from '@angular/http'; in order to prevent name clashes.

The problem addressed here is that request() method has two different call signatures. When Request object is passed instead of the URL string, the options argument is ignored by Angular. So both cases must be properly handled.

And here's the example of how to register this overridden class with DI container:

export const httpProvider = {
  provide: NgHttp,
  useFactory: httpFactory,
  deps: [XHRBackend, RequestOptions, AuthenticationStateService]
};


export function httpFactory (
  xhrBackend: XHRBackend,
  requestOptions: RequestOptions,
  authenticationStateService: AuthenticationStateService
): Http {
  return new Http(
    xhrBackend,
    requestOptions,
    authenticationStateService
  );
}

With such approach you can inject Http class normally, but your overridden class will be magically injected instead. This allows you to integrate your solution easily without changing other parts of the application (polymorphism in action).

Just add httpProvider to the providers property of your module metadata.


Extending BaseRequestOptions might be of great help in this scenario. Check out the following code:

import {provide} from 'angular2/core';
import {bootstrap} from 'angular2/platform/browser';
import {HTTP_PROVIDERS, Headers, Http, BaseRequestOptions} from 'angular2/http';

import {AppCmp} from './components/app/app';


class MyRequestOptions extends BaseRequestOptions {
  constructor () {
    super();
    this.headers.append('My-Custom-Header','MyCustomHeaderValue');
  }
} 

bootstrap(AppCmp, [
  ROUTER_PROVIDERS,
  HTTP_PROVIDERS,
  provide(RequestOptions, { useClass: MyRequestOptions })
]);

This should include 'My-Custom-Header' in every call.

Update:

To be able to change the header anytime you want instead of above code you can also use following code to add a new header:

this.http._defaultOptions.headers.append('Authorization', 'token');

to delete you can do

this.http._defaultOptions.headers.delete('Authorization');

Also there is another function that you can use to set the value:

this.http._defaultOptions.headers.set('Authorization', 'token');

Above solution still is not completely valid in typescript context. _defaultHeaders is protected and not supposed to be used like this. I would recommend the above solution for a quick fix but for long run its better to write your own wrapper around http calls which also handles auth. Take following example from auth0 which is better and clean.

https://github.com/auth0/angular2-jwt/blob/master/angular2-jwt.ts

Update - June 2018 I see a lot of people going for this solution but I would advise otherwise. Appending header globally will send auth token to every api call going out from your app. So the api calls going to third party plugins like intercom or zendesk or any other api will also carry your authorization header. This might result into a big security flaw. So instead, use interceptor globally but check manually if the outgoing call is towards your server's api endpoint or not and then attach auth header.


In Angular 2.1.2 I approached this by extending the angular Http:

import {Injectable} from "@angular/core";
import {Http, Headers, RequestOptionsArgs, Request, Response, ConnectionBackend, RequestOptions} from "@angular/http";
import {Observable} from 'rxjs/Observable';

@Injectable()
export class HttpClient extends Http {

  constructor(protected _backend: ConnectionBackend, protected _defaultOptions: RequestOptions) {

    super(_backend, _defaultOptions);
  }

  _setCustomHeaders(options?: RequestOptionsArgs):RequestOptionsArgs{
    if(!options) {
      options = new RequestOptions({});
    }
    if(localStorage.getItem("id_token")) {

      if (!options.headers) {

        options.headers = new Headers();


      }
      options.headers.set("Authorization", localStorage.getItem("id_token"))
    }
    return options;
  }


  request(url: string|Request, options?: RequestOptionsArgs): Observable<Response> {
    options = this._setCustomHeaders(options);
    return super.request(url, options)
  }
}

then in my App Providers I was able to use a custom Factory to provide 'Http'

import { RequestOptions, Http, XHRBackend} from '@angular/http';
import {HttpClient} from './httpClient';
import { RequestOptions, Http, XHRBackend} from '@angular/http';
import {HttpClient} from './httpClient';//above snippet

function httpClientFactory(xhrBackend: XHRBackend, requestOptions: RequestOptions): Http {
  return new HttpClient(xhrBackend, requestOptions);
}

@NgModule({
  imports:[
    FormsModule,
    BrowserModule,
  ],
  declarations: APP_DECLARATIONS,
  bootstrap:[AppComponent],
  providers:[
     { provide: Http, useFactory: httpClientFactory, deps: [XHRBackend, RequestOptions]}
  ],
})
export class AppModule {
  constructor(){

  }
}

now I don't need to declare every Http method and can use http as normal throughout my application.


You can create your own http client with some authorization header:

import {Injectable} from '@angular/core';
import {HttpClient, HttpHeaders} from '@angular/common/http';

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

  constructor(private http: HttpClient) {}

createAuthorizationHeader(bearerToken: string): HttpHeaders {
  const headerDict = {
    Authorization: 'Bearer ' + bearerToken,
  }
  return new HttpHeaders(headerDict);
}

get<T>(url, bearerToken) {
  this.createAuthorizationHeader(bearerToken);
  return this.http.get<T>(url, {
    headers: this.createAuthorizationHeader(bearerToken)
  });
}

post<T>(url, bearerToken, data) {
  this.createAuthorizationHeader(bearerToken);
  return this.http.post<T>(url, data, {
    headers: this.createAuthorizationHeader(bearerToken)
  });
}
}

And then inject it instead of HttpClient in your service class:

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

  constructor(readonly httpClientWithAuthorization: HttpClientWithAuthorization) {}

  getSomething(): Observable<Object> {
    return this.httpClientWithAuthorization.get<Object>(url,'someBearer');
  }

  postSomething(data) {
    return this.httpClientWithAuthorization.post<Object>(url,'someBearer', data);
  }
}

You can use canActive in your routes, like so:

import { Injectable } from '@angular/core';
import { Router } from '@angular/router';
import { CanActivate } from '@angular/router';
import { AuthService } from './auth.service';

@Injectable()
export class AuthGuard implements CanActivate {

  constructor(private auth: AuthService, private router: Router) {}

  canActivate() {
    // If user is not logged in we'll send them to the homepage 
    if (!this.auth.loggedIn()) {
      this.router.navigate(['']);
      return false;
    }
    return true;
  }

}

const appRoutes: Routes = [
  {
    path: '', redirectTo: '/deals', pathMatch: 'full'
  },
  {
    path: 'special',
    component: PrivateDealsComponent,
    /* We'll use the canActivate API and pass in our AuthGuard.
       Now any time the /special route is hit, the AuthGuard will run
       first to make sure the user is logged in before activating and
       loading this route. */
    canActivate: [AuthGuard]
  }
];

Taken from: https://auth0.com/blog/angular-2-authentication


After some investigation, I found the final and the most easy way is to extend BaseRequestOptions which I prefer.
The following are the ways I tried and give up for some reason:
1. extend BaseRequestOptions, and add dynamic headers in constructor(). It can not work if I login. It will be created once. So it is not dynamic.
2. extend Http. Same reason as above, I can not add dynamic headers in constructor(). And if I rewrite request(..) method, and set headers, like this:

request(url: string|Request, options?: RequestOptionsArgs): Observable<Response> {
 let token = localStorage.getItem(AppConstants.tokenName);
 if (typeof url === 'string') { // meaning we have to add the token to the options, not in url
  if (!options) {
    options = new RequestOptions({});
  }
  options.headers.set('Authorization', 'token_value');
 } else {
  url.headers.set('Authorization', 'token_value');
 }
 return super.request(url, options).catch(this.catchAuthError(this));
}

You just need to overwrite this method, but not every get/post/put methods.

3.And my preferred solution is extend BaseRequestOptions and overwrite merge() :

@Injectable()
export class AuthRequestOptions extends BaseRequestOptions {

 merge(options?: RequestOptionsArgs): RequestOptions {
  var newOptions = super.merge(options);
  let token = localStorage.getItem(AppConstants.tokenName);
  newOptions.headers.set(AppConstants.authHeaderName, token);
  return newOptions;
 }
}

this merge() function will be called for every request.


There were some changes for angular 2.0.1 and higher:

    import {RequestOptions, RequestMethod, Headers} from '@angular/http';
    import { BrowserModule } from '@angular/platform-browser';
    import { HttpModule }     from '@angular/http';
    import { AppRoutingModule } from './app.routing.module';   
    import { AppComponent }  from './app.component';

    //you can move this class to a better place
    class GlobalHttpOptions extends RequestOptions {
        constructor() { 
          super({ 
            method: RequestMethod.Get,
            headers: new Headers({
              'MyHeader': 'MyHeaderValue',
            })
          });
        }
      }

    @NgModule({

      imports:      [ BrowserModule, HttpModule, AppRoutingModule ],
      declarations: [ AppComponent],
      bootstrap:    [ AppComponent ],
      providers:    [ { provide: RequestOptions, useClass: GlobalHttpOptions} ]
    })

    export class AppModule { }

Here is an improved version of the accepted answer, updated for Angular2 final :

import {Injectable} from "@angular/core";
import {Http, Headers, Response, Request, BaseRequestOptions, RequestMethod} from "@angular/http";
import {I18nService} from "../lang-picker/i18n.service";
import {Observable} from "rxjs";
@Injectable()
export class HttpClient {

    constructor(private http: Http, private i18n: I18nService ) {}

    get(url:string):Observable<Response> {
        return this.request(url, RequestMethod.Get);
    }

    post(url:string, body:any) {   
        return this.request(url, RequestMethod.Post, body);
    }

    private request(url:string, method:RequestMethod, body?:any):Observable<Response>{

        let headers = new Headers();
        this.createAcceptLanguageHeader(headers);

        let options = new BaseRequestOptions();
        options.headers = headers;
        options.url = url;
        options.method = method;
        options.body = body;
        options.withCredentials = true;

        let request = new Request(options);

        return this.http.request(request);
    }

    // set the accept-language header using the value from i18n service that holds the language currently selected by the user
    private createAcceptLanguageHeader(headers:Headers) {

        headers.append('Accept-Language', this.i18n.getCurrentLang());
    }
}

Of course it should be extended for methods like delete and put if needed (I don't need them yet at this point in my project).

The advantage is that there is less duplicated code in the get/post/... methods.

Note that in my case I use cookies for authentication. I needed the header for i18n (the Accept-Language header) because many values returned by our API are translated in the user's language. In my app the i18n service holds the language currently selected by the user.


This is how I did for setting token with every request.

import { RequestOptions, BaseRequestOptions, RequestOptionsArgs } from '@angular/http';

export class CustomRequestOptions extends BaseRequestOptions {

    constructor() {
        super();
        this.headers.set('Content-Type', 'application/json');
    }
    merge(options?: RequestOptionsArgs): RequestOptions {
        const token = localStorage.getItem('token');
        const newOptions = super.merge(options);
        if (token) {
            newOptions.headers.set('Authorization', `Bearer ${token}`);
        }

        return newOptions;
    }
}

And register in app.module.ts

@NgModule({
    declarations: [
        AppComponent
    ],
    imports: [
        BrowserModule
    ],
    providers: [
        { provide: RequestOptions, useClass: CustomRequestOptions }
    ],
    bootstrap: [AppComponent]
})
export class AppModule { }

HTTP interceptors are now available via the new HttpClient from @angular/common/http, as of Angular 4.3.x versions and beyond.

It's pretty simple to add a header for every request now:

import {
  HttpEvent,
  HttpInterceptor,
  HttpHandler,
  HttpRequest,
} from '@angular/common/http';
import { Observable } from 'rxjs';
 
export class AddHeaderInterceptor implements HttpInterceptor {
  intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    // Clone the request to add the new header
    const clonedRequest = req.clone({ headers: req.headers.append('Authorization', 'Bearer 123') });

    // Pass the cloned request instead of the original request to the next handle
    return next.handle(clonedRequest);
  }
}

There's a principle of immutability, that's the reason the request needs to be cloned before setting something new on it.

As editing headers is a very common task, there's actually a shortcut for it (while cloning the request):

const clonedRequest = req.clone({ setHeaders: { Authorization: 'Bearer 123' } });

After creating the interceptor, you should register it using the HTTP_INTERCEPTORS provide.

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

@NgModule({
  providers: [{
    provide: HTTP_INTERCEPTORS,
    useClass: AddHeaderInterceptor,
    multi: true,
  }],
})
export class AppModule {}

For Angular 5 and above, we can use HttpInterceptor for generalizing the request and response operations. This helps us avoid duplicating:

1) Common headers

2) Specifying response type

3) Querying request

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

@Injectable()
export class AuthHttpInterceptor implements HttpInterceptor {

  requestCounter: number = 0;
  constructor() {
  }

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

    request = request.clone({
      responseType: 'json',
      setHeaders: {
        Authorization: `Bearer token_value`,
        'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'
      }
    });

    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) {
        // do stuff with response error if you want
      }
    });
  }
}

We can use this AuthHttpInterceptor class as a provider for the HttpInterceptors:

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { AppComponent } from './app.component';
import { AppRoutingModule } from './app.routing-module';
import { AuthHttpInterceptor } from './services/auth-http.interceptor';
import { HttpClientModule, HTTP_INTERCEPTORS } from '@angular/common/http';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    AppRoutingModule,
    HttpClientModule,
    BrowserAnimationsModule,
  ],
  providers: [
    {
      provide: HTTP_INTERCEPTORS,
      useClass: AuthHttpInterceptor,
      multi: true
    }
  ],
  exports: [],
  bootstrap: [AppComponent]
})
export class AppModule {
}

I has able to choose a simplier solution > Add a new Headers to the defaults options merge or load by your api get (or other) function.

get(endpoint: string, params?: any, options?: RequestOptions) {
  if (!options) {
    options = new RequestOptions();
    options.headers = new Headers( { "Accept": "application/json" } ); <<<<
  }
  // [...] 
}

Of course you can externalize this Headers in default options or whatever in your class. This is in the Ionic generated api.ts @Injectable() export class API {}

It is very quick and it work for me. I didn't want json/ld format.


Create a custom Http class by extending the Angular 2 Http Provider and simply override the constructor and request method in you custom Http class. The example below adds Authorization header in every http request.

import {Injectable} from '@angular/core';
import {Http, XHRBackend, RequestOptions, Request, RequestOptionsArgs, Response, Headers} from '@angular/http';
import {Observable} from 'rxjs/Observable';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/catch';

@Injectable()
export class HttpService extends Http {

  constructor (backend: XHRBackend, options: RequestOptions) {
    let token = localStorage.getItem('auth_token'); // your custom token getter function here
    options.headers.set('Authorization', `Bearer ${token}`);
    super(backend, options);
  }

  request(url: string|Request, options?: RequestOptionsArgs): Observable<Response> {
    let token = localStorage.getItem('auth_token');
    if (typeof url === 'string') { // meaning we have to add the token to the options, not in url
      if (!options) {
        // let's make option object
        options = {headers: new Headers()};
      }
      options.headers.set('Authorization', `Bearer ${token}`);
    } else {
    // we have to add the token to the url object
      url.headers.set('Authorization', `Bearer ${token}`);
    }
    return super.request(url, options).catch(this.catchAuthError(this));
  }

  private catchAuthError (self: HttpService) {
    // we have to pass HttpService's own instance here as `self`
    return (res: Response) => {
      console.log(res);
      if (res.status === 401 || res.status === 403) {
        // if not authenticated
        console.log(res);
      }
      return Observable.throw(res);
    };
  }
}

Then configure your main app.module.ts to provide the XHRBackend as the ConnectionBackend provider and the RequestOptions to your custom Http class:

import { HttpModule, RequestOptions, XHRBackend } from '@angular/http';
import { HttpService } from './services/http.service';
...
@NgModule({
  imports: [..],
  providers: [
    {
      provide: HttpService,
      useFactory: (backend: XHRBackend, options: RequestOptions) => {
        return new HttpService(backend, options);
      },
      deps: [XHRBackend, RequestOptions]
    }
  ],
  bootstrap: [ AppComponent ]
})

After that, you can now use your custom http provider in your services. For example:

import { Injectable }     from '@angular/core';
import {HttpService} from './http.service';

@Injectable()
class UserService {
  constructor (private http: HttpService) {}

  // token will added automatically to get request header
  getUser (id: number) {
    return this.http.get(`/users/${id}`).map((res) => {
      return res.json();
    } );
  }
}

Here's a comprehensive guide - http://adonespitogo.com/articles/angular-2-extending-http-provider/


Better late than never... =)

You may take the concept of extended BaseRequestOptions(from here https://angular.io/docs/ts/latest/guide/server-communication.html#!#override-default-request-options) and refresh the headers "on the fly" (not only in constructor). You may use getter/setter "headers" property override like this:

import { Injectable } from '@angular/core';
import { BaseRequestOptions, RequestOptions, Headers } from '@angular/http';

@Injectable()
export class DefaultRequestOptions extends BaseRequestOptions {

    private superHeaders: Headers;

    get headers() {
        // Set the default 'Content-Type' header
        this.superHeaders.set('Content-Type', 'application/json');

        const token = localStorage.getItem('authToken');
        if(token) {
            this.superHeaders.set('Authorization', `Bearer ${token}`);
        } else {
            this.superHeaders.delete('Authorization');
        }
        return this.superHeaders;
    }

    set headers(headers: Headers) {
        this.superHeaders = headers;
    }

    constructor() {
        super();
    }
}

export const requestOptionsProvider = { provide: RequestOptions, useClass: DefaultRequestOptions };

Although I'm answering this very late but if anyone is seeking an easier solution.

We can use angular2-jwt. angular2-jwt is useful automatically attaching a JSON Web Token (JWT) as an Authorization header when making HTTP requests from an Angular 2 app.

We can set global headers with advanced configuration option

export function authHttpServiceFactory(http: Http, options: RequestOptions) {
  return new AuthHttp(new AuthConfig({
    tokenName: 'token',
        tokenGetter: (() => sessionStorage.getItem('token')),
        globalHeaders: [{'Content-Type':'application/json'}],
    }), http, options);
}

And sending per request token like

    getThing() {
  let myHeader = new Headers();
  myHeader.append('Content-Type', 'application/json');

  this.authHttp.get('http://example.com/api/thing', { headers: myHeader })
    .subscribe(
      data => this.thing = data,
      err => console.log(error),
      () => console.log('Request Complete')
    );

  // Pass it after the body in a POST request
  this.authHttp.post('http://example.com/api/thing', 'post body', { headers: myHeader })
    .subscribe(
      data => this.thing = data,
      err => console.log(error),
      () => console.log('Request Complete')
    );
}

The simplest of all

Create a config.ts file

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

export class Config {
    url: string = 'http://localhost:3000';
    httpOptions: any = {
        headers: new HttpHeaders({
           'Content-Type': 'application/json',
           'Authorization': JSON.parse(localStorage.getItem('currentUser')).token
        })
    }
}

Then on your service, just import the config.ts file

import { Config } from '../config';
import { HttpClient } from '@angular/common/http';

@Injectable()
export class OrganizationService {
  config = new Config;

  constructor(
    private http: HttpClient
  ) { }

  addData(data): Observable<any> {
     let sendAddLink = `${this.config.url}/api/addData`;

     return this.http.post(sendAddLink , data, this.config.httpOptions).pipe(
       tap(snap => {
      return snap;
        })
    );
 } 

I think it was the simplest and the safest.