Best Practices for Adding Headers in Angular Applications
In an Angular project, it happens frequently to have requests or requests builder that are used to communicate with the backend.
A 'junior' developer's approach is to re-add the same headers to each request, this could work but it is not a good practice (DRY principle violation):
- in case of change of requirements, the code has to be changed (and tested) in multiple places
- there is a bigger risk of typos or other mistakes
DRY Principle: Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.
Service or Interceptors?
A simple approach could be to generate the headers in a centralized place, in a service. In this case, the service is often used to generate the full requests to the backend.
If we want to leave more 'freedom' to local services to generate their own HTTP requests, we can delegate this task to an interceptor.
You can find more information about interceptors in the Angular documentation.
Interceptor example
Here we have a simple example of an interceptor that catches each request and adds the headers to it.
In this specific case, the JSON content type is added to each request, but only if the body is not a FormData object.
The FormData uses the multipart/form-data
content type, and it should not be overridden.
import { Injectable } from '@angular/core';
import { HttpEvent, HttpHandler, HttpInterceptor, HttpRequest } from '@angular/common/http';
import { Observable } from 'rxjs';
@Injectable()
export class HttpHeadersInterceptor implements HttpInterceptor {
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
let httpReq = req;
if (!(req.body instanceof FormData)) {
// Additional headers
const headers = {
'Content-Type': 'application/json'
};
// Clone the request and set the new headers
httpReq = req.clone({ setHeaders: headers });
}
// Send cloned request with header to the next handler
return next.handle(httpReq);
}
}
setHeaders
will add the new headers to the request, but it will not remove the existing ones.
To trigger the interceptor, we have to add it to the main.ts
file in the providers
section:
bootstrapApplication(AppComponent, {
providers: [
{ provide: HTTP_INTERCEPTORS, useClass: HttpHeadersInterceptor, multi: true },
...