Angular - Set headers for every request
To answer, you question you could provide a service that wraps the original Http
object from Angular. Something like described below.
import {Injectable} from '@angular/core';
import {Http, Headers} from '@angular/http';
@Injectable()
export class HttpClient {
constructor(private http: Http) {}
createAuthorizationHeader(headers: Headers) {
headers.append('Authorization', 'Basic ' +
btoa('username:password'));
}
get(url) {
let headers = new Headers();
this.createAuthorizationHeader(headers);
return this.http.get(url, {
headers: headers
});
}
post(url, data) {
let headers = new Headers();
this.createAuthorizationHeader(headers);
return this.http.post(url, data, {
headers: headers
});
}
}
And instead of injecting the Http
object you could inject this one (HttpClient
).
import { HttpClient } from './http-client';
export class MyComponent {
// Notice we inject "our" HttpClient here, naming it Http so it's easier
constructor(http: HttpClient) {
this.http = httpClient;
}
handleSomething() {
this.http.post(url, data).subscribe(result => {
// console.log( result );
});
}
}
I also think that something could be done using multi providers for the Http
class by providing your own class extending the Http
one... See this link: http://blog.thoughtram.io/angular2/2015/11/23/multi-providers-in-angular-2.html.
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.
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 {}
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]
})