Skip to content

Commit 569f028

Browse files
fix: added a option to choose between legacy and the new request/response interceptor ordering
* test: add request interceptor tests for legacy and ordered execution * feat: add legacy interceptor request/response ordering option --------- Co-authored-by: Jay <jasonsaayman@gmail.com>
1 parent 44b7c9f commit 569f028

File tree

6 files changed

+89
-17
lines changed

6 files changed

+89
-17
lines changed

README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -615,6 +615,9 @@ These are the available config options for making requests. Only the `url` is re
615615

616616
// throw ETIMEDOUT error instead of generic ECONNABORTED on request timeouts
617617
clarifyTimeoutError: false,
618+
619+
// use the legacy interceptor request/response ordering
620+
legacyInterceptorReqResOrdering: true, // default
618621
},
619622

620623
env: {

index.d.cts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -302,6 +302,7 @@ declare namespace axios {
302302
silentJSONParsing?: boolean;
303303
forcedJSONParsing?: boolean;
304304
clarifyTimeoutError?: boolean;
305+
legacyInterceptorReqResOrdering?: boolean;
305306
}
306307

307308
interface GenericAbortSignal {

index.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -332,6 +332,7 @@ export interface TransitionalOptions {
332332
silentJSONParsing?: boolean;
333333
forcedJSONParsing?: boolean;
334334
clarifyTimeoutError?: boolean;
335+
legacyInterceptorReqResOrdering?: boolean;
335336
}
336337

337338
export interface GenericAbortSignal {

lib/core/Axios.js

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import mergeConfig from './mergeConfig.js';
88
import buildFullPath from './buildFullPath.js';
99
import validator from '../helpers/validator.js';
1010
import AxiosHeaders from './AxiosHeaders.js';
11+
import transitionalDefaults from '../defaults/transitional.js';
1112

1213
const validators = validator.validators;
1314

@@ -80,7 +81,8 @@ class Axios {
8081
validator.assertOptions(transitional, {
8182
silentJSONParsing: validators.transitional(validators.boolean),
8283
forcedJSONParsing: validators.transitional(validators.boolean),
83-
clarifyTimeoutError: validators.transitional(validators.boolean)
84+
clarifyTimeoutError: validators.transitional(validators.boolean),
85+
legacyInterceptorReqResOrdering: validators.transitional(validators.boolean)
8486
}, false);
8587
}
8688

@@ -139,7 +141,14 @@ class Axios {
139141

140142
synchronousRequestInterceptors = synchronousRequestInterceptors && interceptor.synchronous;
141143

142-
requestInterceptorChain.unshift(interceptor.fulfilled, interceptor.rejected);
144+
const transitional = config.transitional || transitionalDefaults;
145+
const legacyInterceptorReqResOrdering = transitional && transitional.legacyInterceptorReqResOrdering;
146+
147+
if (legacyInterceptorReqResOrdering) {
148+
requestInterceptorChain.unshift(interceptor.fulfilled, interceptor.rejected);
149+
} else {
150+
requestInterceptorChain.push(interceptor.fulfilled, interceptor.rejected);
151+
}
143152
});
144153

145154
const responseInterceptorChain = [];

lib/defaults/transitional.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,6 @@
33
export default {
44
silentJSONParsing: true,
55
forcedJSONParsing: true,
6-
clarifyTimeoutError: false
6+
clarifyTimeoutError: false,
7+
legacyInterceptorReqResOrdering: true
78
};

test/specs/interceptors.spec.js

Lines changed: 71 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,63 @@ describe('interceptors', function () {
9191
});
9292
});
9393

94+
it('should execute request interceptor in legacy order', function (done) {
95+
let sequence = '';
96+
axios.interceptors.request.use(function (config) {
97+
sequence += '1';
98+
return config;
99+
});
100+
101+
axios.interceptors.request.use(function (config) {
102+
sequence += '2';
103+
return config;
104+
});
105+
106+
axios.interceptors.request.use(function (config) {
107+
sequence += '3';
108+
return config;
109+
});
110+
111+
axios({
112+
url: '/foo',
113+
});
114+
115+
getAjaxRequest().then(function (request) {
116+
expect(sequence).toBe('321');
117+
done();
118+
});
119+
});
120+
121+
it('should execute request interceptor in order', function (done) {
122+
let sequence = '';
123+
axios.interceptors.request.use(function (config) {
124+
sequence += '1';
125+
return config;
126+
});
127+
128+
axios.interceptors.request.use(function (config) {
129+
sequence += '2';
130+
return config;
131+
});
132+
133+
axios.interceptors.request.use(function (config) {
134+
sequence += '3';
135+
return config;
136+
});
137+
138+
axios({
139+
url: '/foo',
140+
transitional: {
141+
legacyInterceptorReqResOrdering: false
142+
}
143+
});
144+
145+
getAjaxRequest().then(function (request) {
146+
expect(sequence).toBe('123');
147+
done();
148+
});
149+
});
150+
94151
it('runs the interceptor if runWhen function is provided and resolves to true', function (done) {
95152
function onGetCall(config) {
96153
return config.method === 'get';
@@ -343,7 +400,7 @@ describe('interceptors', function () {
343400

344401
function fireRequestAndExpect(expectation) {
345402
let response;
346-
axios('/foo').then(function(data) {
403+
axios('/foo').then(function (data) {
347404
response = data;
348405
});
349406
getAjaxRequest().then(function (request) {
@@ -352,7 +409,7 @@ describe('interceptors', function () {
352409
responseText: 'OK'
353410
});
354411

355-
setTimeout(function() {
412+
setTimeout(function () {
356413
expectation(response)
357414
}, 100);
358415
});
@@ -384,10 +441,10 @@ describe('interceptors', function () {
384441
});
385442

386443
it('then only the last interceptor\'s result is returned', function (done) {
387-
axios.interceptors.response.use(function() {
444+
axios.interceptors.response.use(function () {
388445
return 'response 1';
389446
});
390-
axios.interceptors.response.use(function() {
447+
axios.interceptors.response.use(function () {
391448
return 'response 2';
392449
});
393450

@@ -398,10 +455,10 @@ describe('interceptors', function () {
398455
});
399456

400457
it('then every interceptor receives the result of it\'s predecessor', function (done) {
401-
axios.interceptors.response.use(function() {
458+
axios.interceptors.response.use(function () {
402459
return 'response 1';
403460
});
404-
axios.interceptors.response.use(function(response) {
461+
axios.interceptors.response.use(function (response) {
405462
return [response, 'response 2'];
406463
});
407464

@@ -414,7 +471,7 @@ describe('interceptors', function () {
414471
describe('and when the fulfillment-interceptor throws', function () {
415472

416473
function fireRequestCatchAndExpect(expectation) {
417-
axios('/foo').catch(function(data) {
474+
axios('/foo').catch(function (data) {
418475
// dont handle result
419476
});
420477
getAjaxRequest().then(function (request) {
@@ -423,14 +480,14 @@ describe('interceptors', function () {
423480
responseText: 'OK'
424481
});
425482

426-
setTimeout(function() {
483+
setTimeout(function () {
427484
expectation()
428485
}, 100);
429486
});
430487
}
431488

432489
it('then the following fulfillment-interceptor is not called', function (done) {
433-
axios.interceptors.response.use(function() {
490+
axios.interceptors.response.use(function () {
434491
throw Error('throwing interceptor');
435492
});
436493
const interceptor2 = jasmine.createSpy('interceptor2');
@@ -443,10 +500,10 @@ describe('interceptors', function () {
443500
});
444501

445502
it('then the following rejection-interceptor is called', function (done) {
446-
axios.interceptors.response.use(function() {
503+
axios.interceptors.response.use(function () {
447504
throw Error('throwing interceptor');
448505
});
449-
const unusedFulfillInterceptor = function() {};
506+
const unusedFulfillInterceptor = function () { };
450507
const rejectIntercept = jasmine.createSpy('rejectIntercept');
451508
axios.interceptors.response.use(unusedFulfillInterceptor, rejectIntercept);
452509

@@ -457,12 +514,12 @@ describe('interceptors', function () {
457514
});
458515

459516
it('once caught, another following fulfill-interceptor is called again (just like in a promise chain)', function (done) {
460-
axios.interceptors.response.use(function() {
517+
axios.interceptors.response.use(function () {
461518
throw Error('throwing interceptor');
462519
});
463520

464-
const unusedFulfillInterceptor = function() {};
465-
const catchingThrowingInterceptor = function() {};
521+
const unusedFulfillInterceptor = function () { };
522+
const catchingThrowingInterceptor = function () { };
466523
axios.interceptors.response.use(unusedFulfillInterceptor, catchingThrowingInterceptor);
467524

468525
const interceptor3 = jasmine.createSpy('interceptor3');

0 commit comments

Comments
 (0)