Ora

How to Pass Values in Headers in Angular?

Published in Angular HTTP Headers 5 mins read

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 custom X-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 or Content-Type for all requests.

Interceptor Example

  1. Create the Interceptor:
    Generate an interceptor using Angular CLI:

    ng generate interceptor auth

    This will create auth.interceptor.ts (or similar) and update app.module.ts.

  2. Modify the Interceptor File:
    Inside auth.interceptor.ts, implement the intercept 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);
      }
    }
  3. Register the Interceptor:
    You need to provide the interceptor in your app.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 that HTTP_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 new HttpHeaders 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 or PUT requests, explicitly setting the Content-Type header (e.g., application/json) is good practice, although HttpClient often infers it correctly for JSON data.
  • Order of Interceptors: If you have multiple interceptors, their order in the providers array of app.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.