Skip to main content

Angular HTTP Headers

HTTP headers are an essential part of HTTP requests and responses. They contain important metadata about the request or response such as content type, authentication tokens, caching directives, and more. In Angular applications, effectively managing HTTP headers is crucial for secure and efficient communication with backend services.

Introduction to HTTP Headers in Angular

When your Angular application communicates with a server, you often need to include specific information in the request headers or read information from the response headers. Angular's HttpClient makes this process straightforward through the HttpHeaders class.

HTTP headers serve several important purposes:

  • Authentication and authorization (Bearer tokens, API keys)
  • Content negotiation (specifying content types)
  • Caching controls
  • Tracking and analytics
  • CORS (Cross-Origin Resource Sharing) requirements

Setting Up HttpClient

Before we start working with headers, make sure you have the HttpClientModule imported in your application:

typescript
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { HttpClientModule } from '@angular/common/http';
import { AppComponent } from './app.component';

@NgModule({
declarations: [AppComponent],
imports: [
BrowserModule,
HttpClientModule // Import HttpClientModule
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }

Creating and Using HTTP Headers

Basic Header Creation

You can create headers using the HttpHeaders class:

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

@Injectable({
providedIn: 'root'
})
export class DataService {
constructor(private http: HttpClient) { }

getData() {
// Create headers
const headers = new HttpHeaders({
'Content-Type': 'application/json',
'Authorization': 'Bearer your-token-here'
});

// Use headers in the request
return this.http.get('https://api.example.com/data', { headers });
}
}

Immutability of HttpHeaders

An important thing to understand about HttpHeaders is that they are immutable. This means that methods like set(), append(), and delete() don't modify the original headers object but return a new one:

typescript
// This doesn't modify the original headers
headers.set('Authorization', 'Bearer new-token');

// The correct way is to assign the result back to a variable
const newHeaders = headers.set('Authorization', 'Bearer new-token');

Common Header Methods

The HttpHeaders class provides several useful methods:

typescript
// Create an empty headers object
let headers = new HttpHeaders();

// Set a single header (returns a new object)
headers = headers.set('Content-Type', 'application/json');

// Append a value to an existing header (adds a value if the header exists)
headers = headers.append('X-Custom-Header', 'value1');

// Multiple values for the same header
headers = headers.append('X-Custom-Header', 'value2');
// Now X-Custom-Header has both values: ['value1', 'value2']

// Check if a header exists
const hasAuth = headers.has('Authorization'); // returns boolean

// Get header value(s)
const contentType = headers.get('Content-Type'); // returns string or null
const allCustomValues = headers.getAll('X-Custom-Header'); // returns array or null

// Delete a header
headers = headers.delete('X-Custom-Header');

Practical Examples

Example 1: Authentication Headers

A common use case is adding authentication tokens to your requests:

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

@Injectable({
providedIn: 'root'
})
export class AuthService {
private apiUrl = 'https://api.example.com';
private token: string = ''; // This would typically come from your auth flow

constructor(private http: HttpClient) { }

login(credentials: { username: string, password: string }) {
return this.http.post<{token: string}>(`${this.apiUrl}/login`, credentials)
.pipe(
tap(response => {
this.token = response.token;
localStorage.setItem('auth_token', this.token);
})
);
}

getProtectedData() {
const token = localStorage.getItem('auth_token') || '';
const headers = new HttpHeaders({
'Authorization': `Bearer ${token}`
});

return this.http.get(`${this.apiUrl}/protected-data`, { headers });
}
}

Don't forget to import tap:

typescript
import { tap } from 'rxjs/operators';

Example 2: Setting Content Type for Different Requests

Different API endpoints might require different content types:

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

@Injectable({
providedIn: 'root'
})
export class ContentService {
constructor(private http: HttpClient) { }

// JSON content type for typical API requests
postJsonData(data: any) {
const headers = new HttpHeaders({
'Content-Type': 'application/json'
});

return this.http.post('https://api.example.com/data', data, { headers });
}

// Form data for file uploads
uploadFile(file: File) {
const formData = new FormData();
formData.append('file', file);

// Note: Don't set Content-Type when sending FormData
// The browser will set the content type including the boundary
return this.http.post('https://api.example.com/upload', formData);
}

// URL encoded form submission
submitForm(formData: any) {
const headers = new HttpHeaders({
'Content-Type': 'application/x-www-form-urlencoded'
});

// Convert object to URL encoded string
const body = Object.keys(formData)
.map(key => encodeURIComponent(key) + '=' + encodeURIComponent(formData[key]))
.join('&');

return this.http.post('https://api.example.com/submit-form', body, { headers });
}
}

Example 3: Reading Response Headers

Sometimes you need to extract information from response headers:

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

@Injectable({
providedIn: 'root'
})
export class PaginationService {
constructor(private http: HttpClient) { }

getPaginatedData(page: number): Observable<HttpResponse<any[]>> {
return this.http.get<any[]>('https://api.example.com/data', {
params: { page: page.toString() },
observe: 'response' // This returns the full response including headers
});
}

// Usage example
displayPageData(page: number) {
this.getPaginatedData(page).subscribe(response => {
// Extract data from the response body
const data = response.body;

// Read pagination headers
const totalItems = response.headers.get('X-Total-Count');
const linkHeader = response.headers.get('Link');

console.log(`Total items: ${totalItems}`);
console.log(`Link header: ${linkHeader}`);

// Process the data
// ...
});
}
}

Example 4: Creating an HTTP Interceptor for Headers

For applying headers consistently across all requests, you can create an HTTP interceptor:

typescript
import { Injectable } from '@angular/core';
import {
HttpRequest,
HttpHandler,
HttpEvent,
HttpInterceptor
} from '@angular/common/http';
import { Observable } from 'rxjs';

@Injectable()
export class HeadersInterceptor implements HttpInterceptor {
constructor() {}

intercept(request: HttpRequest<unknown>, next: HttpHandler): Observable<HttpEvent<unknown>> {
// Get token from localStorage
const token = localStorage.getItem('auth_token');

// Clone the request and add headers
const modifiedRequest = request.clone({
setHeaders: {
'Content-Type': 'application/json',
'Accept': 'application/json',
'X-App-Version': '1.0.0',
// Only add Authorization if the token exists
...(token ? { 'Authorization': `Bearer ${token}` } : {})
}
});

// Forward the modified request
return next.handle(modifiedRequest);
}
}

To register the interceptor, add it to your AppModule providers:

typescript
import { NgModule } from '@angular/core';
import { HTTP_INTERCEPTORS, HttpClientModule } from '@angular/common/http';
import { HeadersInterceptor } from './interceptors/headers.interceptor';

@NgModule({
// ...other module configuration
imports: [HttpClientModule],
providers: [
{
provide: HTTP_INTERCEPTORS,
useClass: HeadersInterceptor,
multi: true
}
]
})
export class AppModule { }

Common HTTP Headers and Their Uses

Here are some commonly used HTTP headers and their purposes:

HeaderPurpose
AuthorizationContains authentication credentials (e.g., Bearer token)
Content-TypeSpecifies the media type of the resource (e.g., application/json)
AcceptSpecifies what content types the client can process
Cache-ControlDirectives for caching mechanisms
X-Requested-WithCustom header, often set to 'XMLHttpRequest' for AJAX requests
OriginIndicates the origin that caused the request (for CORS)
X-CSRF-TOKENUsed for CSRF protection

Error Handling with Headers

Sometimes you need to handle errors differently based on response headers:

typescript
import { HttpClient, HttpErrorResponse } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { catchError, throwError } from 'rxjs';

@Injectable({
providedIn: 'root'
})
export class ErrorHandlingService {
constructor(private http: HttpClient) { }

getData() {
return this.http.get('https://api.example.com/data')
.pipe(
catchError((error: HttpErrorResponse) => {
// Check for specific headers in the error response
if (error.headers.has('X-Error-Type')) {
const errorType = error.headers.get('X-Error-Type');

switch(errorType) {
case 'validation':
console.error('Validation error:', error.error);
break;
case 'maintenance':
console.error('Service maintenance in progress');
break;
default:
console.error('Unknown error type');
}
}

return throwError(() => new Error('Something went wrong'));
})
);
}
}

Summary

HTTP headers are a critical part of web communication that allow you to customize your HTTP requests and extract metadata from responses. In Angular:

  1. Use the HttpHeaders class to create and manage request headers
  2. Remember that HttpHeaders objects are immutable
  3. Apply consistent headers using HTTP interceptors
  4. Extract valuable information from response headers
  5. Set appropriate content types for different types of requests
  6. Implement authentication using authorization headers

By mastering HTTP headers in Angular, you can build more secure, efficient, and feature-rich web applications that communicate effectively with backend services.

Additional Resources

Exercises

  1. Create a service that uses different content types for different endpoints
  2. Implement an HTTP interceptor that adds authentication headers from a token service
  3. Create a service that reads pagination information from response headers
  4. Build a file upload service with progress tracking (hint: use reportProgress: true)
  5. Create a caching service that uses HTTP headers like ETag and Last-Modified to efficiently fetch data


If you spot any mistakes on this website, please let me know at [email protected]. I’d greatly appreciate your feedback! :)