HTTP & Data
Interceptors
The invisible middleman. Manipulate every HTTP request centrally in one place without having to touch 50 different files.
Imagine you have built 50 services in your app. Suddenly, the backend team says: "Hey, from now on, we need an Authorization header on every single request."
Without interceptors, you would have to open 50 files and manually copy-paste the header logic. Nightmare.
With an Interceptor, you write this code exactly once. It hooks into the HTTP pipeline like a filter. Every request leaving your app must pass through this checkpoint – automatically.
1. The Pipeline Simulation
Send a request below. Observe how the interceptor catches the request "on the fly," injects the token, and only then forwards it to the server.
2. Implementation
Since Angular 15+, we use Functional Interceptors. Forget the old Class-based boilerplate. An interceptor is now just a simple arrow function.
Step 1: Write the Function
The most important concept here is Immutability. A common mistake is trying to modify req directly. Angular forbids this to prevent side effects. You must use req.clone() to create a modified copy.
import { HttpInterceptorFn } from '@angular/common/http';
import { inject } from '@angular/core';
export const authInterceptor: HttpInterceptorFn = (req, next) => {
// 1. Get the token (e.g. from AuthService or LocalStorage)
const token = 'my-secret-jwt-token';
// 2. Clone and Modify
// IMPORTANT: Requests in Angular are immutable!
// You cannot do 'req.headers.set(...)'. You MUST create a clone.
const authReq = req.clone({
setHeaders: {
Authorization: `Bearer ${token}`
}
});
// 3. Forward the request
// 'next' passes the modified request to the next interceptor
// or finally to the backend.
return next(authReq);
};Step 2: Register Globally
To make Angular use the interceptor, we need to register it in our app.config.ts provider.
// app.config.ts
import { ApplicationConfig } from '@angular/core';
import { provideHttpClient, withInterceptors } from '@angular/common/http';
import { authInterceptor } from './core/interceptors/auth.interceptor';
export const appConfig: ApplicationConfig = {
providers: [
provideHttpClient(
// The order matters! They are executed in sequence.
withInterceptors([
authInterceptor,
// loggingInterceptor,
// errorInterceptor
])
)
]
};Response Handling: Interceptors also work in the other direction (incoming responses). I use this for Global Error Handling: If the backend returns a 401 (Unauthorized), I catch it here and redirect to the login page centrally.