From 82847f737ef9d468493720b8bc3664fb0ddc7757 Mon Sep 17 00:00:00 2001 From: Matt Zabriskie Date: Thu, 24 Dec 2015 11:44:46 -0700 Subject: [PATCH] Fixing config weirdness --- lib/adapters/http.js | 16 +---- lib/adapters/xhr.js | 32 +++------ lib/axios.js | 40 ++++++++---- lib/utils.js | 6 +- test/specs/defaults.spec.js | 116 +++++++++++++++++++++++++++++++++ test/specs/utils/merge.spec.js | 15 +++++ 6 files changed, 176 insertions(+), 49 deletions(-) diff --git a/lib/adapters/http.js b/lib/adapters/http.js index be64e50..7a916a5 100644 --- a/lib/adapters/http.js +++ b/lib/adapters/http.js @@ -1,6 +1,5 @@ 'use strict'; -var defaults = require('./../defaults'); var utils = require('./../utils'); var buildURL = require('./../helpers/buildURL'); var transformData = require('./../helpers/transformData'); @@ -12,19 +11,8 @@ var pkg = require('./../../package.json'); var Buffer = require('buffer').Buffer; module.exports = function httpAdapter(resolve, reject, config) { - // Transform request data - var data = transformData( - config.data, - config.headers, - config.transformRequest - ); - - // Merge headers - var headers = utils.merge( - defaults.headers.common, - defaults.headers[config.method] || {}, - config.headers || {} - ); + var data = config.data; + var headers = config.headers; // Set User-Agent (required by some servers) // Only set header if it hasn't been set in config diff --git a/lib/adapters/xhr.js b/lib/adapters/xhr.js index e7be067..f5b9853 100644 --- a/lib/adapters/xhr.js +++ b/lib/adapters/xhr.js @@ -2,7 +2,6 @@ /*global ActiveXObject:true*/ -var defaults = require('./../defaults'); var utils = require('./../utils'); var buildURL = require('./../helpers/buildURL'); var parseHeaders = require('./../helpers/parseHeaders'); @@ -12,21 +11,10 @@ var ieVersion = require('./../helpers/ieVersion'); var btoa = window.btoa || require('./../helpers/btoa'); module.exports = function xhrAdapter(resolve, reject, config) { - // Transform request data - var data = transformData( - config.data, - config.headers, - config.transformRequest - ); + var requestData = config.data; + var requestHeaders = config.headers; - // Merge headers - var requestHeaders = utils.merge( - defaults.headers.common, - defaults.headers[config.method] || {}, - config.headers || {} - ); - - if (utils.isFormData(data)) { + if (utils.isFormData(requestData)) { delete requestHeaders['Content-Type']; // Let the browser set it } @@ -89,19 +77,19 @@ module.exports = function xhrAdapter(resolve, reject, config) { var cookies = require('./../helpers/cookies'); // Add xsrf header - var xsrfValue = config.withCredentials || isURLSameOrigin(config.url) ? - cookies.read(config.xsrfCookieName || defaults.xsrfCookieName) : + var xsrfValue = config.withCredentials || isURLSameOrigin(config.url) ? + cookies.read(config.xsrfCookieName) : undefined; if (xsrfValue) { - requestHeaders[config.xsrfHeaderName || defaults.xsrfHeaderName] = xsrfValue; + requestHeaders[config.xsrfHeaderName] = xsrfValue; } } // Add headers to the request if (!xDomain) { utils.forEach(requestHeaders, function setRequestHeader(val, key) { - if (!data && key.toLowerCase() === 'content-type') { + if (!requestData && key.toLowerCase() === 'content-type') { // Remove Content-Type if data is undefined delete requestHeaders[key]; } else { @@ -127,10 +115,10 @@ module.exports = function xhrAdapter(resolve, reject, config) { } } - if (utils.isArrayBuffer(data)) { - data = new DataView(data); + if (utils.isArrayBuffer(requestData)) { + requestData = new DataView(requestData); } // Send the request - request.send(data); + request.send(requestData); }; diff --git a/lib/axios.js b/lib/axios.js index 9e2d3a8..1a32b75 100644 --- a/lib/axios.js +++ b/lib/axios.js @@ -7,15 +7,10 @@ var InterceptorManager = require('./core/InterceptorManager'); var isAbsoluteURL = require('./helpers/isAbsoluteURL'); var combineURLs = require('./helpers/combineURLs'); var bind = require('./helpers/bind'); +var transformData = require('./helpers/transformData'); function Axios(defaultConfig) { - this.defaultConfig = utils.merge({ - headers: {}, - timeout: defaults.timeout, - transformRequest: defaults.transformRequest, - transformResponse: defaults.transformResponse - }, defaultConfig); - + this.defaults = utils.merge({}, defaultConfig); this.interceptors = { request: new InterceptorManager(), response: new InterceptorManager() @@ -31,14 +26,36 @@ Axios.prototype.request = function request(config) { }, arguments[1]); } - config = utils.merge(this.defaultConfig, { method: 'get' }, config); + config = utils.merge(defaults, this.defaults, { method: 'get' }, config); + // Support baseURL config if (config.baseURL && !isAbsoluteURL(config.url)) { config.url = combineURLs(config.baseURL, config.url); } // Don't allow overriding defaults.withCredentials - config.withCredentials = config.withCredentials || defaults.withCredentials; + config.withCredentials = config.withCredentials || this.defaults.withCredentials; + + // Transform request data + config.data = transformData( + config.data, + config.headers, + config.transformRequest + ); + + // Flatten headers + config.headers = utils.merge( + config.headers.common || {}, + config.headers[config.method] || {}, + config.headers || {} + ); + + utils.forEach( + ['delete', 'get', 'head', 'post', 'put', 'patch', 'common'], + function cleanHeaderConfig(method) { + delete config.headers[method]; + } + ); // Hook up interceptors middleware var chain = [dispatchRequest, undefined]; @@ -59,8 +76,7 @@ Axios.prototype.request = function request(config) { return promise; }; -var defaultInstance = new Axios(); - +var defaultInstance = new Axios(defaults); var axios = module.exports = bind(Axios.prototype.request, defaultInstance); axios.create = function create(defaultConfig) { @@ -68,7 +84,7 @@ axios.create = function create(defaultConfig) { }; // Expose defaults -axios.defaults = defaults; +axios.defaults = defaultInstance.defaults; // Expose all/spread axios.all = function all(promises) { diff --git a/lib/utils.js b/lib/utils.js index fdc4da2..0d418ae 100644 --- a/lib/utils.js +++ b/lib/utils.js @@ -212,7 +212,11 @@ function forEach(obj, fn) { function merge(/* obj1, obj2, obj3, ... */) { var result = {}; function assignValue(val, key) { - result[key] = val; + if (typeof result[key] === 'object' && typeof val === 'object') { + result[key] = merge(result[key], val); + } else { + result[key] = val; + } } for (var i = 0, l = arguments.length; i < l; i++) { diff --git a/test/specs/defaults.spec.js b/test/specs/defaults.spec.js index 9a97653..c283ccb 100644 --- a/test/specs/defaults.spec.js +++ b/test/specs/defaults.spec.js @@ -1,6 +1,22 @@ +var axios = require('../../index'); var defaults = require('../../lib/defaults'); +var utils = require('../../lib/utils'); describe('defaults', function () { + var __defaults; + var XSRF_COOKIE_NAME = 'CUSTOM-XSRF-TOKEN'; + + beforeEach(function () { + jasmine.Ajax.install(); + __defaults = axios.defaults; + }); + + afterEach(function () { + jasmine.Ajax.uninstall(); + axios.defaults = __defaults; + document.cookie = XSRF_COOKIE_NAME + '=;expires=' + new Date(Date.now() - 86400000).toGMTString(); + }); + it('should transform request json', function () { expect(defaults.transformRequest[0]({foo: 'bar'})).toEqual('{"foo":"bar"}'); }); @@ -19,5 +35,105 @@ describe('defaults', function () { it('should do nothing to response string', function () { expect(defaults.transformResponse[0]('foo=bar')).toEqual('foo=bar'); }); + + it('should use global defaults config', function (done) { + var request; + + axios({ url: '/foo' }); + + setTimeout(function () { + request = jasmine.Ajax.requests.mostRecent(); + + expect(request.url).toBe('/foo'); + done(); + }, 0); + }); + + it('should use modified defaults config', function (done) { + var request; + axios.defaults.baseURL = 'http://example.com/'; + + axios({ url: '/foo' }); + + setTimeout(function () { + request = jasmine.Ajax.requests.mostRecent(); + + expect(request.url).toBe('http://example.com/foo'); + done(); + }, 0); + }); + + it('should use request config', function (done) { + var request; + + axios({ + url: '/foo', + baseURL: 'http://www.example.com' + }); + + setTimeout(function () { + request = jasmine.Ajax.requests.mostRecent(); + + expect(request.url).toBe('http://www.example.com/foo'); + done(); + }, 0); + }); + + it('should use default config for custom instance', function (done) { + var request; + var instance = axios.create({ + xsrfCookieName: XSRF_COOKIE_NAME, + xsrfHeaderName: 'X-CUSTOM-XSRF-TOKEN' + }); + document.cookie = instance.defaults.xsrfCookieName + '=foobarbaz'; + + instance.get('/foo'); + + setTimeout(function () { + request = jasmine.Ajax.requests.mostRecent(); + + expect(request.requestHeaders[instance.defaults.xsrfHeaderName]).toEqual('foobarbaz'); + done(); + }, 0); + }); + + it('should use header config', function (done) { + var request; + var instance = axios.create({ + headers: { + common: { + 'X-COMMON-HEADER': 'commonHeaderValue' + }, + get: { + 'X-GET-HEADER': 'getHeaderValue' + }, + post: { + 'X-POST-HEADER': 'postHeaderValue' + } + } + }); + + instance.get('/foo', { + headers: { + 'X-FOO-HEADER': 'fooHeaderValue', + 'X-BAR-HEADER': 'barHeaderValue' + } + }); + + setTimeout(function () { + request = jasmine.Ajax.requests.mostRecent(); + + expect(request.requestHeaders).toEqual( + utils.merge(defaults.headers.common, { + 'X-COMMON-HEADER': 'commonHeaderValue', + 'X-GET-HEADER': 'getHeaderValue', + 'X-FOO-HEADER': 'fooHeaderValue', + 'X-BAR-HEADER': 'barHeaderValue' + }) + ); + done(); + }, 0); + }); + }); diff --git a/test/specs/utils/merge.spec.js b/test/specs/utils/merge.spec.js index 5e826e7..63235d3 100644 --- a/test/specs/utils/merge.spec.js +++ b/test/specs/utils/merge.spec.js @@ -23,5 +23,20 @@ describe('utils::merge', function () { expect(d.foo).toEqual(789); expect(d.bar).toEqual(456); }); + + it('should merge recursively', function () { + var a = {foo: {bar: 123}}; + var b = {foo: {baz: 456}, bar: {qux: 789}}; + + expect(merge(a, b)).toEqual({ + foo: { + bar: 123, + baz: 456 + }, + bar: { + qux: 789 + } + }); + }); });