Fetch Interceptors & Request Middleware0%

Fetch Interceptors & Request Middleware

Beginner12 min read•Updated: Jul 11, 2026
Study Materials

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.

Practice Quiz

Test your understanding of this lesson with 5 questions. Each question has one correct answer.

PrevNext