Skip to content

Commit

Permalink
fix: wrap errors to improve async stack trace (#5987)
Browse files Browse the repository at this point in the history
  • Loading branch information
ikonst committed Jan 24, 2024
1 parent 6d4c421 commit 123f354
Show file tree
Hide file tree
Showing 2 changed files with 91 additions and 8 deletions.
23 changes: 22 additions & 1 deletion lib/core/Axios.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,28 @@ class Axios {
*
* @returns {Promise} The Promise to be fulfilled
*/
request(configOrUrl, config) {
async request(configOrUrl, config) {
try {
return await this._request(configOrUrl, config);
} catch (err) {
const dummy = {}
if (Error.captureStackTrace) {
Error.captureStackTrace(dummy)
} else {
dummy.stack = new Error().stack;
}
// slice off the Error: ... line
dummy.stack = dummy.stack.replace(/^.+\n/, '');
// match without the 2 top stack lines
if (!err.stack.endsWith(dummy.stack.replace(/^.+\n.+\n/, ''))) {
err.stack += '\n' + dummy.stack
}

throw err;
}
}

_request(configOrUrl, config) {
/*eslint no-param-reassign:0*/
// Allow for axios('example/url'[, config]) a la fetch API
if (typeof configOrUrl === 'string') {
Expand Down
76 changes: 69 additions & 7 deletions test/unit/adapters/http.js
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,9 @@ function toleranceRange(positive, negative) {
}
}

const nodeVersion = process.versions.node.split('.').map(v => parseInt(v, 10));
const nodeMajorVersion = nodeVersion[0];

var noop = ()=> {};

const LOCAL_SERVER_URL = 'http://localhost:4444';
Expand Down Expand Up @@ -446,6 +449,57 @@ describe('supports http with nodejs', function () {
});
});

it('should wrap HTTP errors and keep stack', function (done) {
if (nodeMajorVersion <= 12) {
this.skip(); // node 12 support for async stack traces appears lacking
return;
}
server = http.createServer(function (req, res) {
res.statusCode = 400;
res.end();
}).listen(4444, function () {
void assert.rejects(
async function findMeInStackTrace() {
await axios.head('http://localhost:4444/one')
},
function (err) {
assert.equal(err.name, 'AxiosError')
assert.equal(err.isAxiosError, true)
const matches = [...err.stack.matchAll(/findMeInStackTrace/g)]
assert.equal(matches.length, 1, err.stack)
return true;
}
).then(done).catch(done);
});
});

it('should wrap interceptor errors and keep stack', function (done) {
if (nodeMajorVersion <= 12) {
this.skip(); // node 12 support for async stack traces appears lacking
return;
}
const axiosInstance = axios.create();
axiosInstance.interceptors.request.use((res) => {
throw new Error('from request interceptor')
});
server = http.createServer(function (req, res) {
res.end();
}).listen(4444, function () {
void assert.rejects(
async function findMeInStackTrace() {
await axiosInstance.get('http://localhost:4444/one')
},
function (err) {
assert.equal(err.name, 'Error')
assert.equal(err.message, 'from request interceptor')
const matches = [...err.stack.matchAll(/findMeInStackTrace/g)]
assert.equal(matches.length, 1, err.stack)
return true;
}
).then(done).catch(done);
});
});

it('should preserve the HTTP verb on redirect', function (done) {
server = http.createServer(function (req, res) {
if (req.method.toLowerCase() !== "head") {
Expand Down Expand Up @@ -1384,13 +1438,21 @@ describe('supports http with nodejs', function () {
// call cancel() when the request has been sent, but a response has not been received
source.cancel('Operation has been canceled.');
}).listen(4444, function () {
axios.get('http://localhost:4444/', {
cancelToken: source.token
}).catch(function (thrown) {
assert.ok(thrown instanceof axios.Cancel, 'Promise must be rejected with a CanceledError object');
assert.equal(thrown.message, 'Operation has been canceled.');
done();
});
void assert.rejects(
async function findMeInStackTrace() {
await axios.get('http://localhost:4444/', {
cancelToken: source.token
});
},
function (thrown) {
assert.ok(thrown instanceof axios.Cancel, 'Promise must be rejected with a CanceledError object');
assert.equal(thrown.message, 'Operation has been canceled.');
if (nodeMajorVersion > 12) {
assert.match(thrown.stack, /findMeInStackTrace/);
}
return true;
},
).then(done).catch(done);
});
});

Expand Down

0 comments on commit 123f354

Please sign in to comment.