In Angular, you primarily pass values in HTTP headers using the HttpClient
service, either directly within your service methods or globally through an HttpInterceptor
. This allows you to include essential information like authentication tokens, content types, or custom metadata with your requests to a backend server.
1. Using HttpHeaders
Directly in HttpClient
Requests
For requests where you need specific headers for a particular API call, you can create an HttpHeaders
object and pass it as an option to your HttpClient
method (e.g., get
, post
, put
, delete
).
The HttpHeaders
class is immutable, meaning methods like set()
return a new HttpHeaders
instance with the updated value, rather than modifying the existing one. This makes header manipulation predictable.
Basic HttpHeaders
Setup
You can initialize HttpHeaders
with an object or chain set()
calls. A common example, as often needed for secure communication, is passing an authorization
header, which specifies the authentication credentials. This is typically done as a key-value pair, such as 'Authorization': 'Bearer your_token_here'
.
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs';
@Injectable({
providedIn: 'root'
})
export class DataService {
private apiUrl = 'https://api.example.com/data';
constructor(private http: HttpClient) { }
getDataWithCustomHeader(): Observable<any> {
// 1. Initialize HttpHeaders directly with an object
// This example demonstrates passing 'Authorization' as a key-value pair.
const headers = new HttpHeaders({
'Content-Type': 'application/json',
'Authorization': 'Bearer YOUR_AUTH_TOKEN_HERE', // Example of an 'authorization' key-pair value
'X-Custom-Header': 'Angular-App'
});
// 2. Or, initialize and chain set() calls
// let headers = new HttpHeaders();
// headers = headers.set('Content-Type', 'application/json');
// headers = headers.set('Authorization', 'Bearer YOUR_AUTH_TOKEN_HERE');
// headers = headers.set('X-Custom-Header', 'Angular-App');
return this.http.get(this.apiUrl, { headers: headers });
}
postDataWithAuth(data: any, token: string): Observable<any> {
const headers = new HttpHeaders().set('Authorization', `Bearer ${token}`);
return this.http.post(this.apiUrl, data, { headers: headers });
}
}
In this example:
- We create a
HttpHeaders
instance. - We set
Content-Type
,Authorization
, and a customX-Custom-Header
. - The
Authorization
header is crucial for sending authentication tokens (e.g., JWTs) to the server. - These headers are then passed within the options object of the
http.get()
method.
2. Implementing an HttpInterceptor
for Global Headers
For headers that need to be sent with most or all outgoing HTTP requests (e.g., authentication tokens, global API keys, or standard Accept
headers), an HttpInterceptor
is the most efficient and maintainable solution. Interceptors allow you to intercept outgoing requests and incoming responses, modifying them as needed.
When to use an HttpInterceptor
- Authentication: Attaching JWT tokens to every outgoing request after a user logs in.
- Logging: Logging request and response details.
- Error Handling: Centralizing error handling logic.
- Caching: Implementing caching strategies.
- Global Headers: Setting default headers like
Accept
orContent-Type
for all requests.
Interceptor Example
-
Create the Interceptor:
Generate an interceptor using Angular CLI:ng generate interceptor auth
This will create
auth.interceptor.ts
(or similar) and updateapp.module.ts
. -
Modify the Interceptor File:
Insideauth.interceptor.ts
, implement theintercept
method. Here, you clone the request and add your desired headers.import { Injectable } from '@angular/core'; import { HttpRequest, HttpHandler, HttpEvent, HttpInterceptor, HttpHeaders } from '@angular/common/http'; import { Observable } from 'rxjs'; @Injectable() export class AuthInterceptor implements HttpInterceptor { constructor() {} intercept(request: HttpRequest<unknown>, next: HttpHandler): Observable<HttpEvent<unknown>> { // Retrieve your token (e.g., from localStorage, a service, or a state management store) const authToken = localStorage.getItem('access_token'); // Or from an AuthService // Clone the request and add the authorization header // This is where we pass the 'Authorization' key-value pair for every request let newHeaders = new HttpHeaders(); if (authToken) { newHeaders = newHeaders.set('Authorization', `Bearer ${authToken}`); } // Add other common headers if needed newHeaders = newHeaders.set('Accept', 'application/json'); newHeaders = newHeaders.set('X-App-Version', '1.0.0'); const authRequest = request.clone({ headers: newHeaders }); // Pass the cloned request to the next handler return next.handle(authRequest); } }
-
Register the Interceptor:
You need to provide the interceptor in yourapp.module.ts
(or a feature module where it's needed).import { NgModule } from '@angular/core'; import { BrowserModule } from '@angular/platform-browser'; import { HttpClientModule, HTTP_INTERCEPTORS } from '@angular/common/http'; import { AppComponent } from './app.component'; import { AuthInterceptor } from './auth.interceptor'; // Import your interceptor @NgModule({ declarations: [ AppComponent ], imports: [ BrowserModule, HttpClientModule // Make sure HttpClientModule is imported ], providers: [ { provide: HTTP_INTERCEPTORS, useClass: AuthInterceptor, multi: true // Essential for providing multiple interceptors } ], bootstrap: [AppComponent] }) export class AppModule { }
The
multi: true
property is crucial as it tells Angular thatHTTP_INTERCEPTORS
is a token for a multi-provider, allowing you to register multiple interceptors.
Key Considerations for Passing Headers
- Immutability: Remember that
HttpHeaders
objects are immutable. Each modification (e.g.,set()
,append()
) returns a newHttpHeaders
instance. Always assign the result back to your variable. - Security: Never store sensitive information like raw authentication tokens directly in your code. Retrieve them securely from
localStorage
,sessionStorage
, or a dedicated authentication service. - CORS (Cross-Origin Resource Sharing): If your frontend and backend are on different domains, the browser will send preflight
OPTIONS
requests. Ensure your backend is configured to handle these and allow custom headers. - Content-Type: For
POST
orPUT
requests, explicitly setting theContent-Type
header (e.g.,application/json
) is good practice, althoughHttpClient
often infers it correctly for JSON data. - Order of Interceptors: If you have multiple interceptors, their order in the
providers
array ofapp.module.ts
matters. Requests flow through them in the order they are provided.
Comparison: Direct Headers vs. Interceptors
Feature | Direct HttpHeaders |
HttpInterceptor |
---|---|---|
Scope | Single, specific HTTP request | Global, for all (or filtered) HTTP requests |
Use Cases | Unique headers for specific API endpoints | Authentication tokens, global API keys, logging |
Maintenance | Can lead to repetitive code for common headers | Centralized header management, highly maintainable |
Flexibility | High, for individual request needs | High, for consistent behavior across the application |
Complexity | Simple for individual requests | Requires an extra class and module registration |
Security Implication | Token logic might be scattered | Token logic is centralized and managed in one place |
By understanding both direct HttpHeaders
usage and HttpInterceptor
implementation, you can effectively manage and pass values in HTTP headers within your Angular applications, leading to cleaner, more efficient, and secure code.