From e0d59eb29bba887cb4376d1c37614dd1c2741327 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rub=C3=A9n=20Norte?= Date: Sat, 8 Apr 2017 21:43:04 +0200 Subject: [PATCH 1/3] Adding failing tests that verify errors contain the request --- test/specs/core/createError.spec.js | 8 ++++++-- test/specs/core/enhanceError.spec.js | 9 +++++++-- test/specs/core/settle.spec.js | 7 ++++++- test/specs/requests.spec.js | 7 ++++--- 4 files changed, 23 insertions(+), 8 deletions(-) diff --git a/test/specs/core/createError.spec.js b/test/specs/core/createError.spec.js index a1e445bc02..b4e18f9d58 100644 --- a/test/specs/core/createError.spec.js +++ b/test/specs/core/createError.spec.js @@ -1,11 +1,15 @@ var createError = require('../../../lib/core/createError'); describe('core::createError', function() { - it('should create an Error with message, config, and code', function() { - var error = createError('Boom!', { foo: 'bar' }, 'ESOMETHING'); + it('should create an Error with message, config, code, request and response', function() { + var request = { path: '/foo' }; + var response = { status: 200, data: { foo: 'bar' } }; + var error = createError('Boom!', { foo: 'bar' }, 'ESOMETHING', request, response); expect(error instanceof Error).toBe(true); expect(error.message).toBe('Boom!'); expect(error.config).toEqual({ foo: 'bar' }); expect(error.code).toBe('ESOMETHING'); + expect(error.request).toBe(request); + expect(error.response).toBe(response); }); }); diff --git a/test/specs/core/enhanceError.spec.js b/test/specs/core/enhanceError.spec.js index bb8ba2230e..0b7c936cb1 100644 --- a/test/specs/core/enhanceError.spec.js +++ b/test/specs/core/enhanceError.spec.js @@ -1,11 +1,16 @@ var enhanceError = require('../../../lib/core/enhanceError'); describe('core::enhanceError', function() { - it('should add config and code to error', function() { + it('should add config, config, request and response to error', function() { var error = new Error('Boom!'); - enhanceError(error, { foo: 'bar' }, 'ESOMETHING'); + var request = { path: '/foo' }; + var response = { status: 200, data: { foo: 'bar' } }; + + enhanceError(error, { foo: 'bar' }, 'ESOMETHING', request, response); expect(error.config).toEqual({ foo: 'bar' }); expect(error.code).toBe('ESOMETHING'); + expect(error.request).toBe(request); + expect(error.response).toBe(response); }); it('should return error', function() { diff --git a/test/specs/core/settle.spec.js b/test/specs/core/settle.spec.js index cc5c15e2a3..914bb9bc64 100644 --- a/test/specs/core/settle.spec.js +++ b/test/specs/core/settle.spec.js @@ -48,13 +48,17 @@ describe('core::settle', function() { }); it('should reject promise if validateStatus returns false', function() { + var req = { + path: '/foo' + }; var response = { status: 500, config: { validateStatus: function() { return false; } - } + }, + request: req }; settle(resolve, reject, response); expect(resolve).not.toHaveBeenCalled(); @@ -63,6 +67,7 @@ describe('core::settle', function() { expect(reason instanceof Error).toBe(true); expect(reason.message).toBe('Request failed with status code 500'); expect(reason.config).toBe(response.config); + expect(reason.request).toBe(req); expect(reason.response).toBe(response); }); diff --git a/test/specs/requests.spec.js b/test/specs/requests.spec.js index 0ae4726283..ba7ffc606a 100644 --- a/test/specs/requests.spec.js +++ b/test/specs/requests.spec.js @@ -49,15 +49,16 @@ describe('requests', function () { var reason = rejectSpy.calls.first().args[0]; expect(reason instanceof Error).toBe(true); expect(reason.config.method).toBe('get'); - expect(reason.config.url).toBe('http://thisisnotaserver'); + expect(reason.config.url).toBe('http://thisisnotaserver/foo'); + expect(reason.request).toEqual(jasmine.any(XMLHttpRequest)); // re-enable jasmine.Ajax jasmine.Ajax.install(); - + done(); }; - axios('http://thisisnotaserver') + axios('http://thisisnotaserver/foo') .then(resolveSpy, rejectSpy) .then(finish, finish); }); From 22ce6db383bc61adabfd79e5bfe16a7f6c7cebbb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rub=C3=A9n=20Norte?= Date: Sat, 8 Apr 2017 21:44:15 +0200 Subject: [PATCH 2/3] Adding request to error objects when it is available --- lib/adapters/http.js | 9 +++++---- lib/adapters/xhr.js | 5 +++-- lib/core/createError.js | 7 ++++--- lib/core/enhanceError.js | 4 +++- lib/core/settle.js | 1 + 5 files changed, 16 insertions(+), 10 deletions(-) diff --git a/lib/adapters/http.js b/lib/adapters/http.js index 10ad580c64..3048e577b1 100644 --- a/lib/adapters/http.js +++ b/lib/adapters/http.js @@ -172,13 +172,14 @@ module.exports = function httpAdapter(config) { // make sure the content length is not over the maxContentLength if specified if (config.maxContentLength > -1 && Buffer.concat(responseBuffer).length > config.maxContentLength) { - reject(createError('maxContentLength size of ' + config.maxContentLength + ' exceeded', config)); + reject(createError('maxContentLength size of ' + config.maxContentLength + ' exceeded', + config, null, lastRequest)); } }); stream.on('error', function handleStreamError(err) { if (aborted) return; - reject(enhanceError(err, config)); + reject(enhanceError(err, config, null, lastRequest)); }); stream.on('end', function handleStreamEnd() { @@ -196,14 +197,14 @@ module.exports = function httpAdapter(config) { // Handle errors req.on('error', function handleRequestError(err) { if (aborted) return; - reject(enhanceError(err, config)); + reject(enhanceError(err, config, null, req)); }); // Handle request timeout if (config.timeout && !timer) { timer = setTimeout(function handleRequestTimeout() { req.abort(); - reject(createError('timeout of ' + config.timeout + 'ms exceeded', config, 'ECONNABORTED')); + reject(createError('timeout of ' + config.timeout + 'ms exceeded', config, 'ECONNABORTED', req)); aborted = true; }, config.timeout); } diff --git a/lib/adapters/xhr.js b/lib/adapters/xhr.js index befd4fb809..6cbce355ae 100644 --- a/lib/adapters/xhr.js +++ b/lib/adapters/xhr.js @@ -84,7 +84,7 @@ module.exports = function xhrAdapter(config) { request.onerror = function handleError() { // Real errors are hidden from us by the browser // onerror should only fire if it's a network error - reject(createError('Network Error', config)); + reject(createError('Network Error', config, null, request)); // Clean up request request = null; @@ -92,7 +92,8 @@ module.exports = function xhrAdapter(config) { // Handle timeout request.ontimeout = function handleTimeout() { - reject(createError('timeout of ' + config.timeout + 'ms exceeded', config, 'ECONNABORTED')); + reject(createError('timeout of ' + config.timeout + 'ms exceeded', config, 'ECONNABORTED', + request)); // Clean up request request = null; diff --git a/lib/core/createError.js b/lib/core/createError.js index aa9abfd595..6b31165348 100644 --- a/lib/core/createError.js +++ b/lib/core/createError.js @@ -3,15 +3,16 @@ var enhanceError = require('./enhanceError'); /** - * Create an Error with the specified message, config, error code, and response. + * Create an Error with the specified message, config, error code, request and response. * * @param {string} message The error message. * @param {Object} config The config. * @param {string} [code] The error code (for example, 'ECONNABORTED'). + @ @param {Object} [request] The request. @ @param {Object} [response] The response. * @returns {Error} The created error. */ -module.exports = function createError(message, config, code, response) { +module.exports = function createError(message, config, code, request, response) { var error = new Error(message); - return enhanceError(error, config, code, response); + return enhanceError(error, config, code, request, response); }; diff --git a/lib/core/enhanceError.js b/lib/core/enhanceError.js index adf836f6d9..23e50114ad 100644 --- a/lib/core/enhanceError.js +++ b/lib/core/enhanceError.js @@ -6,14 +6,16 @@ * @param {Error} error The error to update. * @param {Object} config The config. * @param {string} [code] The error code (for example, 'ECONNABORTED'). + @ @param {Object} [request] The request. @ @param {Object} [response] The response. * @returns {Error} The error. */ -module.exports = function enhanceError(error, config, code, response) { +module.exports = function enhanceError(error, config, code, request, response) { error.config = config; if (code) { error.code = code; } + error.request = request; error.response = response; return error; }; diff --git a/lib/core/settle.js b/lib/core/settle.js index 00ed6361ab..8db5e23ca9 100644 --- a/lib/core/settle.js +++ b/lib/core/settle.js @@ -19,6 +19,7 @@ module.exports = function settle(resolve, reject, response) { 'Request failed with status code ' + response.status, response.config, null, + response.request, response )); } From 1e76ea36f3d631cb68779d28d445a9da58dac189 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rub=C3=A9n=20Norte?= Date: Sat, 8 Apr 2017 21:44:41 +0200 Subject: [PATCH 3/3] Adding documentation for error.request --- README.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index a7bf758fc2..f48ea588c7 100644 --- a/README.md +++ b/README.md @@ -469,11 +469,16 @@ instance.interceptors.request.use(function () {/*...*/}); axios.get('/user/12345') .catch(function (error) { if (error.response) { - // The request was made, but the server responded with a status code + // The request was made and the server responded with a status code // that falls out of the range of 2xx console.log(error.response.data); console.log(error.response.status); console.log(error.response.headers); + } else if (error.request) { + // The request was made but no response was received + // `error.request` is an instance of XMLHttpRequest in the browser and an instance of + // http.ClientRequest in node.js + console.log(error.request); } else { // Something happened in setting up the request that triggered an Error console.log('Error', error.message);