npm-axios

Description
Promise based HTTP client for the browser and node.js
Author
tessl
Last updated

How to use

npx @tessl/cli registry install tessl/npm-axios@0.30.0

interceptors.md docs/

1
# Interceptors
2
3
Request and response interceptors provide a middleware system for transforming requests before they're sent and responses before they're handled by your code. This enables powerful patterns like automatic authentication, request/response logging, error handling, and data transformation.
4
5
## Capabilities
6
7
### Request Interceptors
8
9
Transform or modify requests before they are sent to the server.
10
11
```javascript { .api }
12
/**
13
* Add request interceptor
14
* @param onFulfilled - Function to transform successful requests
15
* @param onRejected - Function to handle request errors
16
* @param options - Optional interceptor configuration
17
* @returns Interceptor ID for later removal
18
*/
19
axios.interceptors.request.use(
20
onFulfilled?: (config: AxiosRequestConfig) => AxiosRequestConfig | Promise<AxiosRequestConfig>,
21
onRejected?: (error: any) => any,
22
options?: AxiosInterceptorOptions
23
): number;
24
```
25
26
**Usage Examples:**
27
28
```javascript
29
// Add authentication token to all requests
30
axios.interceptors.request.use(
31
(config) => {
32
const token = localStorage.getItem('authToken');
33
if (token) {
34
config.headers.Authorization = `Bearer ${token}`;
35
}
36
return config;
37
},
38
(error) => {
39
return Promise.reject(error);
40
}
41
);
42
43
// Log all outgoing requests
44
axios.interceptors.request.use(
45
(config) => {
46
console.log(`Making ${config.method?.toUpperCase()} request to ${config.url}`);
47
console.log('Request config:', config);
48
return config;
49
}
50
);
51
52
// Async request transformation
53
axios.interceptors.request.use(
54
async (config) => {
55
// Get fresh token asynchronously
56
const token = await getValidToken();
57
config.headers.Authorization = `Bearer ${token}`;
58
return config;
59
}
60
);
61
62
// Conditional interceptor with runWhen
63
axios.interceptors.request.use(
64
(config) => {
65
config.headers['X-Request-Source'] = 'web-app';
66
return config;
67
},
68
null,
69
{
70
runWhen: (config) => config.url?.includes('/api/') === true
71
}
72
);
73
```
74
75
### Response Interceptors
76
77
Transform or handle responses before they reach your application code.
78
79
```javascript { .api }
80
/**
81
* Add response interceptor
82
* @param onFulfilled - Function to transform successful responses
83
* @param onRejected - Function to handle response errors
84
* @param options - Optional interceptor configuration
85
* @returns Interceptor ID for later removal
86
*/
87
axios.interceptors.response.use(
88
onFulfilled?: (response: AxiosResponse) => AxiosResponse | Promise<AxiosResponse>,
89
onRejected?: (error: any) => any,
90
options?: AxiosInterceptorOptions
91
): number;
92
```
93
94
**Usage Examples:**
95
96
```javascript
97
// Transform response data
98
axios.interceptors.response.use(
99
(response) => {
100
// Extract data from wrapper object
101
if (response.data && response.data.result) {
102
response.data = response.data.result;
103
}
104
return response;
105
},
106
(error) => {
107
return Promise.reject(error);
108
}
109
);
110
111
// Handle token expiration globally
112
axios.interceptors.response.use(
113
(response) => response,
114
async (error) => {
115
if (error.response?.status === 401) {
116
// Token expired, try to refresh
117
try {
118
const newToken = await refreshAuthToken();
119
localStorage.setItem('authToken', newToken);
120
121
// Retry original request with new token
122
const originalRequest = error.config;
123
originalRequest.headers.Authorization = `Bearer ${newToken}`;
124
return axios(originalRequest);
125
} catch (refreshError) {
126
// Refresh failed, redirect to login
127
window.location.href = '/login';
128
return Promise.reject(refreshError);
129
}
130
}
131
return Promise.reject(error);
132
}
133
);
134
135
// Log response details
136
axios.interceptors.response.use(
137
(response) => {
138
console.log(`Response ${response.status} from ${response.config.url}`);
139
console.log('Response time:', Date.now() - response.config.metadata?.startTime);
140
return response;
141
},
142
(error) => {
143
console.error('Request failed:', error.message);
144
return Promise.reject(error);
145
}
146
);
147
```
148
149
### Interceptor Management
150
151
Manage (remove, clear, inspect) existing interceptors.
152
153
```javascript { .api }
154
/**
155
* Remove request interceptor by ID
156
* @param id - Interceptor ID returned from use()
157
*/
158
axios.interceptors.request.eject(id: number): void;
159
160
/**
161
* Remove response interceptor by ID
162
* @param id - Interceptor ID returned from use()
163
*/
164
axios.interceptors.response.eject(id: number): void;
165
166
/**
167
* Clear all request interceptors
168
*/
169
axios.interceptors.request.clear(): void;
170
171
/**
172
* Clear all response interceptors
173
*/
174
axios.interceptors.response.clear(): void;
175
176
/**
177
* Iterate over all registered request interceptors
178
* @param fn - Function called for each interceptor
179
*/
180
axios.interceptors.request.forEach(fn: (interceptor: any) => void): void;
181
182
/**
183
* Iterate over all registered response interceptors
184
* @param fn - Function called for each interceptor
185
*/
186
axios.interceptors.response.forEach(fn: (interceptor: any) => void): void;
187
```
188
189
**Usage Examples:**
190
191
```javascript
192
// Add interceptor and store ID
193
const requestInterceptorId = axios.interceptors.request.use(
194
(config) => {
195
config.headers['X-Custom-Header'] = 'value';
196
return config;
197
}
198
);
199
200
// Remove interceptor later
201
axios.interceptors.request.eject(requestInterceptorId);
202
203
// Clear all request interceptors
204
axios.interceptors.request.clear();
205
206
// Clear all response interceptors
207
axios.interceptors.response.clear();
208
209
// Temporary interceptor for specific operation
210
const tempInterceptor = axios.interceptors.response.use(
211
(response) => {
212
console.log('Temporary logging active');
213
return response;
214
}
215
);
216
217
// Perform operations with temporary interceptor
218
await performSomeOperations();
219
220
// Remove temporary interceptor
221
axios.interceptors.response.eject(tempInterceptor);
222
223
// Clear all interceptors for cleanup
224
axios.interceptors.request.clear();
225
axios.interceptors.response.clear();
226
```
227
228
### Interceptor Configuration Options
229
230
Advanced interceptor configuration for specialized behavior.
231
232
```javascript { .api }
233
interface AxiosInterceptorOptions {
234
/** Whether the interceptor should run synchronously (default: false) */
235
synchronous?: boolean;
236
/** Function to determine if interceptor should run for a specific request */
237
runWhen?: (config: AxiosRequestConfig) => boolean;
238
}
239
```
240
241
**Usage Examples:**
242
243
```javascript
244
// Synchronous interceptor (runs immediately, not in Promise chain)
245
axios.interceptors.request.use(
246
(config) => {
247
config.headers['X-Timestamp'] = Date.now().toString();
248
return config;
249
},
250
null,
251
{ synchronous: true }
252
);
253
254
// Conditional interceptor
255
axios.interceptors.request.use(
256
(config) => {
257
config.headers['X-API-Version'] = '2.0';
258
return config;
259
},
260
null,
261
{
262
runWhen: (config) => {
263
// Only run for API calls, not static assets
264
return config.url?.startsWith('/api/') ?? false;
265
}
266
}
267
);
268
269
// Combined options
270
axios.interceptors.response.use(
271
(response) => {
272
// Fast synchronous response transformation
273
response.data = response.data?.data || response.data;
274
return response;
275
},
276
null,
277
{
278
synchronous: true,
279
runWhen: (config) => config.responseType !== 'blob'
280
}
281
);
282
```
283
284
### Interceptor Manager Interface
285
286
The interceptor manager objects accessible via `axios.interceptors.request` and `axios.interceptors.response`.
287
288
```javascript { .api }
289
interface AxiosInterceptorManager<V> {
290
/**
291
* Add an interceptor
292
* @param onFulfilled - Success handler
293
* @param onRejected - Error handler
294
* @param options - Configuration options
295
* @returns Interceptor ID for removal
296
*/
297
use<T = V>(
298
onFulfilled?: (value: V) => T | Promise<T>,
299
onRejected?: (error: any) => any,
300
options?: AxiosInterceptorOptions
301
): number;
302
303
/**
304
* Remove an interceptor by ID
305
* @param id - Interceptor ID from use()
306
*/
307
eject(id: number): void;
308
309
/**
310
* Clear all interceptors
311
*/
312
clear(): void;
313
314
/**
315
* Iterate over registered interceptors
316
* @param fn - Function called for each interceptor
317
*/
318
forEach(fn: (interceptor: any) => void): void;
319
}
320
```
321
322
## Advanced Interceptor Patterns
323
324
### Request/Response Correlation
325
326
Track requests and responses together using metadata:
327
328
```javascript
329
// Request interceptor - add timing
330
axios.interceptors.request.use((config) => {
331
config.metadata = { startTime: Date.now() };
332
return config;
333
});
334
335
// Response interceptor - calculate duration
336
axios.interceptors.response.use((response) => {
337
const duration = Date.now() - response.config.metadata.startTime;
338
console.log(`Request took ${duration}ms`);
339
return response;
340
});
341
```
342
343
### Error Recovery and Retry
344
345
Implement automatic retry logic with exponential backoff:
346
347
```javascript
348
axios.interceptors.response.use(
349
(response) => response,
350
async (error) => {
351
const config = error.config;
352
353
// Don't retry if we've already retried too many times
354
if (!config || config.__retryCount >= 3) {
355
return Promise.reject(error);
356
}
357
358
// Only retry on network errors or 5xx responses
359
if (error.code === 'NETWORK_ERROR' || (error.response && error.response.status >= 500)) {
360
config.__retryCount = config.__retryCount || 0;
361
config.__retryCount += 1;
362
363
// Exponential backoff delay
364
const delay = Math.pow(2, config.__retryCount) * 1000;
365
await new Promise(resolve => setTimeout(resolve, delay));
366
367
return axios(config);
368
}
369
370
return Promise.reject(error);
371
}
372
);
373
```
374
375
### Instance-Specific Interceptors
376
377
Interceptors on custom instances only affect that instance:
378
379
```javascript
380
// Create API client with instance-specific interceptors
381
const apiClient = axios.create({ baseURL: 'https://api.example.com' });
382
383
// This interceptor only affects apiClient requests
384
apiClient.interceptors.request.use((config) => {
385
config.headers['X-Client-Version'] = '1.0';
386
return config;
387
});
388
389
// This interceptor only affects apiClient responses
390
apiClient.interceptors.response.use(
391
(response) => {
392
// Custom response transformation for this API
393
return response;
394
}
395
);
396
397
// Main axios instance is unaffected
398
const otherResponse = await axios.get('https://other-api.com/data'); // No X-Client-Version header
399
```