Skip to content

Commit 97b6f93

Browse files
authoredApr 28, 2022
fix: make arity error message actionable (#1901)
1 parent 05f12a6 commit 97b6f93

File tree

3 files changed

+34
-12
lines changed

3 files changed

+34
-12
lines changed
 

‎lib/chain.js

+21-2
Original file line numberDiff line numberDiff line change
@@ -73,12 +73,31 @@ Chain.prototype.getHandlers = function getHandlers() {
7373
*/
7474
Chain.prototype.add = function add(handler) {
7575
assert.func(handler);
76+
var handlerId = handler._identifier || handler._name || handler.name;
7677
if (handler.length <= 2) {
7778
// arity <= 2, must be AsyncFunction
78-
assert.equal(handler.constructor.name, 'AsyncFunction');
79+
assert.equal(
80+
handler.constructor.name,
81+
'AsyncFunction',
82+
`Handler [${handlerId}] is missing a third argument (the ` +
83+
'"next" callback) but is not an async function. Middlware ' +
84+
'handlers can be either async/await or callback-based.' +
85+
'Callback-based (non-async) handlers should accept three ' +
86+
'arguments: (req, res, next). Async handler functions should ' +
87+
'accept maximum of 2 arguments: (req, res).'
88+
);
7989
} else {
8090
// otherwise shouldn't be AsyncFunction
81-
assert.notEqual(handler.constructor.name, 'AsyncFunction');
91+
assert.notEqual(
92+
handler.constructor.name,
93+
'AsyncFunction',
94+
`Handler [${handlerId}] accepts a third argument (the 'next" ` +
95+
'callback) but is also an async function. Middlware handlers ' +
96+
'can be either async/await or callback-based. Async handler ' +
97+
'functions should accept maximum of 2 arguments: (req, res). ' +
98+
'Non-async handlers should accept three arguments: (req, ' +
99+
'res, next).'
100+
);
82101
}
83102

84103
// _name is assigned in the server and router

‎lib/router.js

+2
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,8 @@ Router.prototype.mount = function mount(opts, handlers) {
205205
handler._name =
206206
handler.name || 'handler-' + self._anonymousHandlerCounter++;
207207

208+
handler._identifier = `${handler._name} on ${opts.method} ${opts.path}`;
209+
208210
// Attach to middleware chain
209211
chain.add(handler);
210212
});

‎test/chain.test.js

+11-10
Original file line numberDiff line numberDiff line change
@@ -409,23 +409,24 @@ test('abort with throw inside async function', function(t) {
409409
});
410410

411411
test('fails to add non async function with arity 2', function(t) {
412+
var handler = function getLunch(req, res) {
413+
res.send('ok');
414+
};
412415
var chain = new Chain();
413-
414416
t.throws(function() {
415-
chain.add(function(req, res) {
416-
res.send('ok');
417-
});
418-
}, Error);
417+
chain.add(handler);
418+
}, /getLunch/);
419419
t.end();
420420
});
421421

422422
test('fails to add async function with arity 3', function(t) {
423-
var chain = new Chain();
423+
var handler = async function getBreakfast(req, res, next) {
424+
res.send('ok');
425+
};
424426

427+
var chain = new Chain();
425428
t.throws(function() {
426-
chain.add(async function(req, res, next) {
427-
res.send('ok');
428-
});
429-
}, Error);
429+
chain.add(handler);
430+
}, /getBreakfast/);
430431
t.end();
431432
});

0 commit comments

Comments
 (0)
Please sign in to comment.