You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
103 lines
2.4 KiB
103 lines
2.4 KiB
1 month ago
|
/**
|
||
|
* Inject raw response, so we can know if middleware has responsed.
|
||
|
*/
|
||
|
function makeInjectedResponse(koaCtx, /*markHandled,*/ whenEnded) {
|
||
|
let res = koaCtx.res;
|
||
|
|
||
|
res.on('close', whenEnded).on('finish', whenEnded);
|
||
|
|
||
|
let dummyRes = Object.create(res);
|
||
|
[
|
||
|
'setHeader',
|
||
|
'writeHead',
|
||
|
'write',
|
||
|
'end'
|
||
|
].forEach(name => {
|
||
|
dummyRes[name] = function (...args) {
|
||
|
res[name](...args);
|
||
|
// koa2.0 initial assign statusCode to 404, reset to 200
|
||
|
if (res.statusCode === 404) {
|
||
|
res.statusCode = 200;
|
||
|
}
|
||
|
// markHandled();
|
||
|
}
|
||
|
});
|
||
|
[
|
||
|
'statusCode',
|
||
|
'statusMessage'
|
||
|
].forEach(name => {
|
||
|
dummyRes.__defineSetter__(name, function (value) {
|
||
|
res[name] = value;
|
||
|
// markHandled();
|
||
|
})
|
||
|
})
|
||
|
|
||
|
return dummyRes;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* The middleware function does include the `next` callback so only resolve
|
||
|
* the Promise when it's called. If it's never called, the middleware stack
|
||
|
* completion will stall
|
||
|
*/
|
||
|
function handler(ctx, connectMiddleware) {
|
||
|
return new Promise((resolve, reject) => {
|
||
|
// let hasHandled = false;
|
||
|
// (req, res)
|
||
|
let args = [
|
||
|
ctx.req,
|
||
|
makeInjectedResponse(
|
||
|
ctx,
|
||
|
// () => {
|
||
|
// // hasHandled = true;
|
||
|
// },
|
||
|
() => {
|
||
|
resolve(false);
|
||
|
})
|
||
|
];
|
||
|
let assumeSync = true
|
||
|
// (req, res, next) or (err, req, res, next)
|
||
|
if (connectMiddleware.length >= 3) {
|
||
|
args.push(err => {
|
||
|
if (err) reject(err)
|
||
|
else resolve(true)
|
||
|
})
|
||
|
assumeSync = false
|
||
|
}
|
||
|
// (err, req, res, next)
|
||
|
if (connectMiddleware.length >= 4) {
|
||
|
args.unshift(null);
|
||
|
}
|
||
|
connectMiddleware(...args)
|
||
|
/**
|
||
|
* If the middleware function does not declare receiving the `next` callback
|
||
|
* assume that it's synchronous.
|
||
|
*/
|
||
|
if (assumeSync /*&& !hasHandled*/) {
|
||
|
resolve(true)
|
||
|
}
|
||
|
})
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Returns a Koa middleware function that varies its async logic based on if the
|
||
|
* given middleware function declares at least 3 parameters, i.e. includes
|
||
|
* the `next` callback function
|
||
|
*/
|
||
|
function koaConnect(connectMiddleware) {
|
||
|
return async (ctx, next) => {
|
||
|
ctx.respond = false;
|
||
|
try {
|
||
|
let goNext = await handler(ctx, connectMiddleware)
|
||
|
if (goNext) {
|
||
|
ctx.respond = true;
|
||
|
return next();
|
||
|
}
|
||
|
} catch (err) {
|
||
|
ctx.respond = true;
|
||
|
throw err;
|
||
|
};
|
||
|
}
|
||
|
}
|
||
|
|
||
|
export = koaConnect
|