2
0
mirror of https://github.com/tenrok/axios.git synced 2026-06-20 20:00:40 +03:00

Merge pull request #27 from jmdobry/feature-interceptors

Adding support for interceptors
This commit is contained in:
Matt Zabriskie
2014-12-08 12:27:48 -07:00
8 changed files with 680 additions and 168 deletions
+1
View File
@@ -16,6 +16,7 @@ module.exports = function(config) {
// list of files / patterns to load in the browser // list of files / patterns to load in the browser
files: [ files: [
'dist/axios.js', 'dist/axios.js',
'node_modules/es6-promise/dist/promise-1.0.0.js',
'test/specs/**/*.spec.js' 'test/specs/**/*.spec.js'
], ],
+37 -1
View File
@@ -13,7 +13,8 @@ var axios = module.exports = function axios(config) {
// Don't allow overriding defaults.withCredentials // Don't allow overriding defaults.withCredentials
config.withCredentials = config.withCredentials || defaults.withCredentials; config.withCredentials = config.withCredentials || defaults.withCredentials;
var promise = new Promise(function (resolve, reject) { var serverRequest = function (config) {
return new Promise(function (resolve, reject) {
try { try {
// For browsers use XHR adapter // For browsers use XHR adapter
if (typeof window !== 'undefined') { if (typeof window !== 'undefined') {
@@ -27,6 +28,7 @@ var axios = module.exports = function axios(config) {
reject(e); reject(e);
} }
}); });
};
function deprecatedMethod(method, instead, docs) { function deprecatedMethod(method, instead, docs) {
try { try {
@@ -41,6 +43,24 @@ var axios = module.exports = function axios(config) {
} catch (e) {} } catch (e) {}
} }
var chain = [serverRequest, undefined];
var promise = Promise.resolve(config);
utils.forEach(axios.interceptors.request.handlers, function (interceptor) {
chain.unshift(interceptor.request, interceptor.requestError);
});
utils.forEach(axios.interceptors.response.handlers, function (interceptor) {
chain.push(interceptor.response, interceptor.responseError);
});
while (chain.length) {
var thenFn = chain.shift();
var rejectFn = chain.shift();
promise = promise.then(thenFn, rejectFn);
}
// Provide alias for success // Provide alias for success
promise.success = function success(fn) { promise.success = function success(fn) {
deprecatedMethod('success', 'then', 'https://github.com/mzabriskie/axios/blob/master/README.md#response-api'); deprecatedMethod('success', 'then', 'https://github.com/mzabriskie/axios/blob/master/README.md#response-api');
@@ -73,6 +93,22 @@ axios.all = function (promises) {
}; };
axios.spread = require('./helpers/spread'); axios.spread = require('./helpers/spread');
// interceptors
axios.interceptors = {
request: {
handlers: [],
use: function (thenFn, rejectFn) {
axios.interceptors.request.handlers.push({ request: thenFn, requestError: rejectFn });
}
},
response: {
handlers: [],
use: function (thenFn, rejectFn) {
axios.interceptors.response.handlers.push({ response: thenFn, responseError: rejectFn });
}
}
};
// Provide aliases for supported request methods // Provide aliases for supported request methods
createShortMethods('delete', 'get', 'head'); createShortMethods('delete', 'get', 'head');
createShortMethodsWithData('post', 'put', 'patch'); createShortMethodsWithData('post', 'put', 'patch');
+299
View File
@@ -0,0 +1,299 @@
describe('interceptors', function () {
beforeEach(function () {
jasmine.Ajax.install();
});
afterEach(function () {
jasmine.Ajax.uninstall();
axios.interceptors.request.handlers = [];
axios.interceptors.response.handlers = [];
});
it('should add a request interceptor', function () {
var request;
runs(function () {
axios.interceptors.request.use(function (config) {
config.headers.test = 'added by interceptor';
return config;
});
axios({
url: '/foo'
});
});
waitsFor(function () {
return request = jasmine.Ajax.requests.mostRecent();
}, 'waiting for the request', 100);
runs(function () {
request.response({
status: 200,
responseText: 'OK'
});
expect(request.requestHeaders.test).toBe('added by interceptor');
});
});
it('should add a request interceptor that returns a new config object', function () {
var request;
runs(function () {
axios.interceptors.request.use(function () {
return {
url: '/bar',
method: 'post'
};
});
axios({
url: '/foo'
});
});
waitsFor(function () {
return request = jasmine.Ajax.requests.mostRecent();
}, 'waiting for the request', 100);
runs(function () {
request.response({
status: 200,
responseText: 'OK'
});
expect(request.method).toBe('post');
expect(request.url).toBe('/bar');
});
});
it('should add a request interceptor that returns a promise', function () {
var request;
runs(function () {
axios.interceptors.request.use(function (config) {
return new Promise(function (resolve) {
// do something async
setTimeout(function () {
config.headers.async = 'promise';
resolve(config);
}, 10);
});
});
axios({
url: '/foo'
});
});
waitsFor(function () {
return request = jasmine.Ajax.requests.mostRecent();
}, 'waiting for the request', 100);
runs(function () {
request.response({
status: 200,
responseText: 'OK'
});
expect(request.requestHeaders.async).toBe('promise');
});
});
it('should add multiple request interceptors', function () {
var request;
runs(function () {
axios.interceptors.request.use(function (config) {
config.headers.test1 = '1';
return config;
});
axios.interceptors.request.use(function (config) {
config.headers.test2 = '2';
return config;
});
axios.interceptors.request.use(function (config) {
config.headers.test3 = '3';
return config;
});
axios({
url: '/foo'
});
});
waitsFor(function () {
return request = jasmine.Ajax.requests.mostRecent();
}, 'waiting for the request', 100);
runs(function () {
request.response({
status: 200,
responseText: 'OK'
});
expect(request.requestHeaders.test1).toBe('1');
expect(request.requestHeaders.test2).toBe('2');
expect(request.requestHeaders.test3).toBe('3');
});
});
it('should add a response interceptor', function () {
var request, response;
runs(function () {
axios.interceptors.response.use(function (data) {
data.data = data.data + ' - modified by interceptor';
return data;
});
axios({
url: '/foo'
}).then(function (data) {
response = data;
});
});
waitsFor(function () {
return request = jasmine.Ajax.requests.mostRecent();
}, 'waiting for the request', 100);
runs(function () {
request.response({
status: 200,
responseText: 'OK'
});
});
waitsFor(function () {
return response;
}, 'waiting for the response', 100);
runs(function () {
expect(response.data).toBe('OK - modified by interceptor');
});
});
it('should add a response interceptor that returns a new data object', function () {
var request, response;
runs(function () {
axios.interceptors.response.use(function () {
return {
data: 'stuff'
};
});
axios({
url: '/foo'
}).then(function (data) {
response = data;
});
});
waitsFor(function () {
return request = jasmine.Ajax.requests.mostRecent();
}, 'waiting for the request', 100);
runs(function () {
request.response({
status: 200,
responseText: 'OK'
});
});
waitsFor(function () {
return response;
}, 'waiting for the response', 100);
runs(function () {
expect(response.data).toBe('stuff');
});
});
it('should add a response interceptor that returns a promise', function () {
var request, response;
runs(function () {
axios.interceptors.response.use(function (data) {
return new Promise(function (resolve) {
// do something async
setTimeout(function () {
data.data = 'you have been promised!';
resolve(data);
}, 10);
});
});
axios({
url: '/foo'
}).then(function (data) {
response = data;
});
});
waitsFor(function () {
return request = jasmine.Ajax.requests.mostRecent();
}, 'waiting for the request', 100);
runs(function () {
request.response({
status: 200,
responseText: 'OK'
});
});
waitsFor(function () {
return response;
}, 'waiting for the response', 100);
runs(function () {
expect(response.data).toBe('you have been promised!');
});
});
it('should add multiple response interceptors', function () {
var request, response;
runs(function () {
axios.interceptors.response.use(function (data) {
data.data = data.data + '1';
return data;
});
axios.interceptors.response.use(function (data) {
data.data = data.data + '2';
return data;
});
axios.interceptors.response.use(function (data) {
data.data = data.data + '3';
return data;
});
axios({
url: '/foo'
}).then(function (data) {
response = data;
});
});
waitsFor(function () {
return request = jasmine.Ajax.requests.mostRecent();
}, 'waiting for the request', 100);
runs(function () {
request.response({
status: 200,
responseText: 'OK'
});
});
waitsFor(function () {
return response;
}, 'waiting for the response', 100);
runs(function () {
expect(response.data).toBe('OK123');
});
});
});
+44 -4
View File
@@ -3,28 +3,53 @@ describe('options', function () {
jasmine.Ajax.install(); jasmine.Ajax.install();
}); });
afterEach(function () {
jasmine.Ajax.uninstall();
});
it('should default method to get', function () { it('should default method to get', function () {
var request;
runs(function () {
axios({ axios({
url: '/foo' url: '/foo'
}); });
});
var request = jasmine.Ajax.requests.mostRecent(); waitsFor(function () {
return request = jasmine.Ajax.requests.mostRecent();
}, 'waiting for the request', 100);
runs(function () {
expect(request.method).toBe('get'); expect(request.method).toBe('get');
}); });
});
it('should accept headers', function () { it('should accept headers', function () {
var request;
runs(function () {
axios({ axios({
url: '/foo', url: '/foo',
headers: { headers: {
'X-Requested-With': 'XMLHttpRequest' 'X-Requested-With': 'XMLHttpRequest'
} }
}); });
});
var request = jasmine.Ajax.requests.mostRecent(); waitsFor(function () {
return request = jasmine.Ajax.requests.mostRecent();
}, 'waiting for the request', 100);
runs(function () {
expect(request.requestHeaders['X-Requested-With']).toEqual('XMLHttpRequest'); expect(request.requestHeaders['X-Requested-With']).toEqual('XMLHttpRequest');
}); });
});
it('should accept params', function () { it('should accept params', function () {
var request;
runs(function () {
axios({ axios({
url: '/foo', url: '/foo',
params: { params: {
@@ -32,20 +57,35 @@ describe('options', function () {
bar: 456 bar: 456
} }
}); });
});
var request = jasmine.Ajax.requests.mostRecent(); waitsFor(function () {
return request = jasmine.Ajax.requests.mostRecent();
}, 'waiting for the request', 100);
runs(function () {
expect(request.url).toBe('/foo?foo=123&bar=456'); expect(request.url).toBe('/foo?foo=123&bar=456');
}); });
});
it('should allow overriding default headers', function () { it('should allow overriding default headers', function () {
var request;
runs(function () {
axios({ axios({
url: '/foo', url: '/foo',
headers: { headers: {
'Accept': 'foo/bar' 'Accept': 'foo/bar'
} }
}); });
});
var request = jasmine.Ajax.requests.mostRecent(); waitsFor(function () {
return request = jasmine.Ajax.requests.mostRecent();
}, 'waiting for the request', 100);
runs(function () {
expect(request.requestHeaders['Accept']).toEqual('foo/bar'); expect(request.requestHeaders['Accept']).toEqual('foo/bar');
}); });
});
}); });
+27 -15
View File
@@ -3,26 +3,35 @@ describe('promise', function () {
jasmine.Ajax.install(); jasmine.Ajax.install();
}); });
it('should provide succinct object to then', function () { afterEach(function () {
var response; jasmine.Ajax.uninstall();
var fulfilled = false; });
it('should provide succinct object to then', function () {
var request, response;
runs(function () {
axios({ axios({
url: '/foo' url: '/foo'
}).then(function (r) { }).then(function (r) {
response = r; response = r;
fulfilled = true; });
}); });
var request = jasmine.Ajax.requests.mostRecent(); waitsFor(function () {
return request = jasmine.Ajax.requests.mostRecent();
}, 'waiting for the request', 100);
runs(function () {
request.response({ request.response({
status: 200, status: 200,
responseText: '{"hello":"world"}' responseText: '{"hello":"world"}'
}); });
});
waitsFor(function () { waitsFor(function () {
return fulfilled; return response;
}); }, 'waiting for the response', 100);
runs(function () { runs(function () {
expect(typeof response).toEqual('object'); expect(typeof response).toEqual('object');
@@ -34,12 +43,9 @@ describe('promise', function () {
}); });
it('should provide verbose arguments to success', function () { it('should provide verbose arguments to success', function () {
var data; var request, data, status, headers, config;
var status;
var headers;
var config;
var fulfilled = false;
runs(function () {
axios({ axios({
url: '/foo' url: '/foo'
}).success(function (d, s, h, c) { }).success(function (d, s, h, c) {
@@ -49,16 +55,22 @@ describe('promise', function () {
config = c; config = c;
fulfilled = true; fulfilled = true;
}); });
});
var request = jasmine.Ajax.requests.mostRecent(); waitsFor(function () {
return request = jasmine.Ajax.requests.mostRecent();
}, 'waiting for the request', 100);
runs(function () {
request.response({ request.response({
status: 200, status: 200,
responseText: '{"hello":"world"}' responseText: '{"hello":"world"}'
}); });
});
waitsFor(function () { waitsFor(function () {
return fulfilled; return data;
}); }, 'waiting for the data', 100);
runs(function () { runs(function () {
expect(data.hello).toEqual('world'); expect(data.hello).toEqual('world');
+40 -4
View File
@@ -3,26 +3,40 @@ describe('transform', function () {
jasmine.Ajax.install(); jasmine.Ajax.install();
}); });
afterEach(function () {
jasmine.Ajax.uninstall();
});
it('should transform JSON to string', function () { it('should transform JSON to string', function () {
var request;
var data = { var data = {
foo: 'bar' foo: 'bar'
}; };
runs(function () {
axios({ axios({
url: '/foo', url: '/foo',
method: 'post', method: 'post',
data: data data: data
}); });
});
var request = jasmine.Ajax.requests.mostRecent(); waitsFor(function () {
return request = jasmine.Ajax.requests.mostRecent();
}, 'waiting for the request', 100);
runs(function () {
expect(request.params).toEqual('{"foo":"bar"}'); expect(request.params).toEqual('{"foo":"bar"}');
}); });
});
it('should override default transform', function () { it('should override default transform', function () {
var request;
var data = { var data = {
foo: 'bar' foo: 'bar'
}; };
runs(function () {
axios({ axios({
url: '/foo', url: '/foo',
method: 'post', method: 'post',
@@ -31,16 +45,24 @@ describe('transform', function () {
return data; return data;
} }
}); });
});
var request = jasmine.Ajax.requests.mostRecent(); waitsFor(function () {
return request = jasmine.Ajax.requests.mostRecent();
}, 'waiting for the request', 100);
runs(function () {
expect(typeof request.params).toEqual('object'); expect(typeof request.params).toEqual('object');
}); });
});
it('should allow an Array of transformers', function () { it('should allow an Array of transformers', function () {
var request;
var data = { var data = {
foo: 'bar' foo: 'bar'
}; };
runs(function () {
axios({ axios({
url: '/foo', url: '/foo',
method: 'post', method: 'post',
@@ -51,22 +73,36 @@ describe('transform', function () {
} }
) )
}); });
});
var request = jasmine.Ajax.requests.mostRecent(); waitsFor(function () {
return request = jasmine.Ajax.requests.mostRecent();
}, 'waiting for the request', 100);
runs(function () {
expect(request.params).toEqual('{"foo":"baz"}'); expect(request.params).toEqual('{"foo":"baz"}');
}); });
});
it('should allowing mutating headers', function () { it('should allowing mutating headers', function () {
var token = Math.floor(Math.random() * Math.pow(2, 64)).toString(36); var token = Math.floor(Math.random() * Math.pow(2, 64)).toString(36);
var request;
runs(function () {
axios({ axios({
url: '/foo', url: '/foo',
transformRequest: function (data, headers) { transformRequest: function (data, headers) {
headers['X-Authorization'] = token; headers['X-Authorization'] = token;
} }
}); });
});
var request = jasmine.Ajax.requests.mostRecent(); waitsFor(function () {
return request = jasmine.Ajax.requests.mostRecent();
}, 'waiting for the request', 100);
runs(function () {
expect(request.requestHeaders['X-Authorization']).toEqual(token); expect(request.requestHeaders['X-Authorization']).toEqual(token);
}); });
});
}); });
+75 -10
View File
@@ -3,46 +3,80 @@ describe('wrapper', function () {
jasmine.Ajax.install(); jasmine.Ajax.install();
}); });
afterEach(function () {
jasmine.Ajax.uninstall();
});
it('should make an http request', function () { it('should make an http request', function () {
var request;
runs(function () {
axios({ axios({
url: '/foo' url: '/foo'
}); });
});
var request = jasmine.Ajax.requests.mostRecent(); waitsFor(function () {
expect(request.url).toBe('/foo'); return request = jasmine.Ajax.requests.mostRecent();
}, 'waiting for the request', 100);
runs(function () {
expect(request.url).toBe('/foo')
});
}); });
it('should default common headers', function () { it('should default common headers', function () {
var request;
var headers = axios.defaults.headers.common;
runs(function () {
axios({ axios({
url: '/foo' url: '/foo'
}); });
});
var request = jasmine.Ajax.requests.mostRecent(); waitsFor(function () {
var headers = axios.defaults.headers.common; return request = jasmine.Ajax.requests.mostRecent();
}, 'waiting for the request', 100);
runs(function () {
for (var key in headers) { for (var key in headers) {
if (headers.hasOwnProperty(key)) { if (headers.hasOwnProperty(key)) {
expect(request.requestHeaders[key]).toEqual(headers[key]); expect(request.requestHeaders[key]).toEqual(headers[key]);
} }
} }
}); });
});
it('should add extra headers for post', function () { it('should add extra headers for post', function () {
var request;
var headers = axios.defaults.headers.common;
runs(function () {
axios({ axios({
method: 'post', method: 'post',
url: '/foo', url: '/foo',
data: 'fizz=buzz' data: 'fizz=buzz'
}); });
});
var request = jasmine.Ajax.requests.mostRecent(); waitsFor(function () {
var headers = axios.defaults.headers.post; return request = jasmine.Ajax.requests.mostRecent();
}, 'waiting for the request', 100);
runs(function () {
for (var key in headers) { for (var key in headers) {
if (headers.hasOwnProperty(key)) { if (headers.hasOwnProperty(key)) {
expect(request.requestHeaders[key]).toEqual(headers[key]); expect(request.requestHeaders[key]).toEqual(headers[key]);
} }
} }
}); });
});
it('should use application/json when posting an object', function () { it('should use application/json when posting an object', function () {
var request;
runs(function () {
axios({ axios({
url: '/foo/bar', url: '/foo/bar',
method: 'post', method: 'post',
@@ -51,54 +85,85 @@ describe('wrapper', function () {
lastName: 'bar' lastName: 'bar'
} }
}); });
});
var request = jasmine.Ajax.requests.mostRecent(); waitsFor(function () {
return request = jasmine.Ajax.requests.mostRecent();
}, 'waiting for the request', 100);
runs(function () {
expect(request.requestHeaders['Content-Type']).toEqual('application/json;charset=utf-8'); expect(request.requestHeaders['Content-Type']).toEqual('application/json;charset=utf-8');
}); });
});
it('should support binary data as array buffer', function () { it('should support binary data as array buffer', function () {
var request;
var input = new Int8Array(2); var input = new Int8Array(2);
input[0] = 1; input[0] = 1;
input[1] = 2; input[1] = 2;
runs(function () {
axios({ axios({
method: 'post', method: 'post',
url: '/foo', url: '/foo',
data: input.buffer data: input.buffer
}); });
});
var request = jasmine.Ajax.requests.mostRecent(); waitsFor(function () {
return request = jasmine.Ajax.requests.mostRecent();
}, 'waiting for the request', 100);
runs(function () {
var output = new Int8Array(request.params.buffer); var output = new Int8Array(request.params.buffer);
expect(output.length).toEqual(2); expect(output.length).toEqual(2);
expect(output[0]).toEqual(1); expect(output[0]).toEqual(1);
expect(output[1]).toEqual(2); expect(output[1]).toEqual(2);
}); });
});
it('should support binary data as array buffer view', function () { it('should support binary data as array buffer view', function () {
var request;
var input = new Int8Array(2); var input = new Int8Array(2);
input[0] = 1; input[0] = 1;
input[1] = 2; input[1] = 2;
runs(function () {
axios({ axios({
method: 'post', method: 'post',
url: '/foo', url: '/foo',
data: input data: input
}); });
});
var request = jasmine.Ajax.requests.mostRecent(); waitsFor(function () {
return request = jasmine.Ajax.requests.mostRecent();
}, 'waiting for the request', 100);
runs(function () {
var output = new Int8Array(request.params.buffer); var output = new Int8Array(request.params.buffer);
expect(output.length).toEqual(2); expect(output.length).toEqual(2);
expect(output[0]).toEqual(1); expect(output[0]).toEqual(1);
expect(output[1]).toEqual(2); expect(output[1]).toEqual(2);
}); });
});
it('should remove content-type if data is empty', function () { it('should remove content-type if data is empty', function () {
var request;
runs(function () {
axios({ axios({
method: 'post', method: 'post',
url: '/foo' url: '/foo'
}); });
});
var request = jasmine.Ajax.requests.mostRecent(); waitsFor(function () {
return request = jasmine.Ajax.requests.mostRecent();
}, 'waiting for the request', 100);
runs(function () {
expect(request.requestHeaders['content-type']).toEqual(undefined); expect(request.requestHeaders['content-type']).toEqual(undefined);
}); });
});
}); });
+25 -2
View File
@@ -1,24 +1,47 @@
describe('xsrf', function () { describe('xsrf', function () {
beforeEach(function () {
jasmine.Ajax.install();
});
afterEach(function () { afterEach(function () {
document.cookie = axios.defaults.xsrfCookieName + '=;expires=' + new Date(Date.now() - 86400000).toGMTString(); document.cookie = axios.defaults.xsrfCookieName + '=;expires=' + new Date(Date.now() - 86400000).toGMTString();
jasmine.Ajax.uninstall();
}); });
it('should not set xsrf header if cookie is null', function () { it('should not set xsrf header if cookie is null', function () {
var request;
runs(function () {
axios({ axios({
url: '/foo' url: '/foo'
}); });
});
var request = jasmine.Ajax.requests.mostRecent(); waitsFor(function () {
return request = jasmine.Ajax.requests.mostRecent();
}, 'waiting for the request', 100);
runs(function () {
expect(request.requestHeaders[axios.defaults.xsrfHeaderName]).toEqual(undefined); expect(request.requestHeaders[axios.defaults.xsrfHeaderName]).toEqual(undefined);
}); });
});
it('should set xsrf header if cookie is set', function () { it('should set xsrf header if cookie is set', function () {
var request;
document.cookie = axios.defaults.xsrfCookieName + '=12345'; document.cookie = axios.defaults.xsrfCookieName + '=12345';
runs(function () {
axios({ axios({
url: '/foo' url: '/foo'
}); });
});
var request = jasmine.Ajax.requests.mostRecent(); waitsFor(function () {
return request = jasmine.Ajax.requests.mostRecent();
}, 'waiting for the request', 100);
runs(function () {
expect(request.requestHeaders[axios.defaults.xsrfHeaderName]).toEqual('12345'); expect(request.requestHeaders[axios.defaults.xsrfHeaderName]).toEqual('12345');
}); });
});
}); });