Fetch Interceptors & Request Middleware0%
Fetch Interceptors & Request Middleware
Beginner12 min read•Updated: Jul 11, 2026
Fetch Interceptors & Request Middleware in Modern JavaScript
While third-party libraries like Axios include built-in request/response interceptors, relying on heavy external dependencies is unnecessary in modern JavaScript. Implementing a Fetch Interceptor Middleware Pipeline allows you to centrally inject authentication tokens, refresh expired JWTs, handle rate limits, and standardize error responses.
1. The Interceptor Pipeline Architecture
Output
Outgoing Request:
fetchRequest ──► [ Auth Header Middleware ] ──► [ Logging Middleware ] ──► HTTP Network
│
Incoming Response: ▼
Client Code ◄── [ Error Transform Middleware ] ◄── [ 401 Refresh Token ] ◄── Response
2. Implementing a Functional Fetch Interceptor Wrapper
JavaScript
class ApiClient {
constructor(baseUrl) {
this.baseUrl = baseUrl;
this.requestInterceptors = [];
this.responseInterceptors = [];
}
// Register request interceptor
useRequest(interceptor) {
this.requestInterceptors.push(interceptor);
}
// Register response interceptor
useResponse(interceptor) {
this.responseInterceptors.push(interceptor);
}
async fetch(endpoint, options = {}) {
let url = `${this.baseUrl}${endpoint}`;
let config = { ...options, headers: { ...options.headers } };
// 1. Execute Request Interceptors in order
for (const interceptor of this.requestInterceptors) {
const modified = await interceptor(url, config);
if (modified) {
url = modified.url || url;
config = modified.config || config;
}
}
// 2. Perform Network Call
let response = await fetch(url, config);
// 3. Execute Response Interceptors in order
for (const interceptor of this.responseInterceptors) {
response = await interceptor(response, { url, config, client: this });
}
return response;
}
}
3. Real-World Interceptor 1: Automatic Auth Bearer Injection
JavaScript
const api = new ApiClient('https://api.enterprise.com/v1');
// Middleware: Attach JWT Token from storage to all requests
api.useRequest(async (url, config) => {
const token = localStorage.getItem('auth_token');
if (token) {
config.headers['Authorization'] = `Bearer ${token}`;
}
config.headers['X-Request-Id'] = crypto.randomUUID();
return { url, config };
});
4. Real-World Interceptor 2: Automatic 401 Token Refresh
When an access token expires, intercept the 401 response, obtain a fresh token using the refresh token, and replay the original request transparently:
JavaScript
api.useResponse(async (response, { url, config, client }) => {
// If unauthorized and we haven't already retried this request:
if (response.status === 401 && !config._isRetry) {
console.warn('Access token expired. Refreshing token...');
try {
// Fetch new access token
const refreshRes = await fetch('https://api.enterprise.com/auth/refresh', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ refreshToken: localStorage.getItem('refresh_token') })
});
if (!refreshRes.ok) throw new Error('Session expired. Please log in again.');
const { accessToken } = await refreshRes.json();
localStorage.setItem('auth_token', accessToken);
// Replay original request with fresh token!
config._isRetry = true;
config.headers['Authorization'] = `Bearer ${accessToken}`;
return await fetch(url, config);
} catch (refreshErr) {
localStorage.clear();
window.location.href = '/login';
throw refreshErr;
}
}
return response;
});
Interactive Quiz
Practice Quiz
Question 1
What is the primary purpose of a Fetch Request Interceptor?
Question 2
How can an interceptor transparently handle an expired JWT token (HTTP 401)?
Question 3
Why is a flag like config._isRetry used in 401 token refresh interceptors?
Question 4
Does the native browser Fetch API include interceptors out of the box?
Question 5
What standard browser method generates unique request tracing IDs for X-Request-Id headers?
Next Lesson
GraphQL Queries, Mutations & Subscriptions
Continue learning with hands-on practice, examples, and exercises in the upcoming topic.
Related Lessons
| Previous Lesson | Next Lesson |
|---|---|
| Server-Sent Events (SSE) | GraphQL Queries, Mutations & Subscriptions |
Practice Quiz
Test your understanding of this lesson with 5 questions. Each question has one correct answer.