feat: new hook type: `response`

Used in authentication middleware. Instead of firing an action
hook, it now fires a response hook.

Response hooks are invoked serially, and if headers are sent from
one of the hook listeners, all subsequent hook methods are not
called.

Response hooks should only be used in situations where res.send
(or other like methods) are invoked. Existing plugin hooks that
pass in res purely for data retrieval purposes have not changed).

fixes nodebb/nodebb-plugin-write-api#101
v1.18.x
Julian Lam 6 years ago
parent 8a64667ff8
commit a23854e3ff

@ -19,9 +19,8 @@ module.exports = function (middleware) {
if (req.loggedIn) {
return next();
}
if (plugins.hasListeners('action:middleware.authenticate')) {
return plugins.fireHook('action:middleware.authenticate', {
if (plugins.hasListeners('response:middleware.authenticate')) {
return plugins.fireHook('response:middleware.authenticate', {
req: req,
res: res,
next: function (err) {

@ -110,6 +110,9 @@ module.exports = function (Plugins) {
case 'static':
fireStaticHook(hook, hookList, params, done);
break;
case 'response':
fireResponseHook(hook, hookList, params, done);
break;
default:
winston.warn('[plugins] Unknown hookType: ' + hookType + ', hook : ' + hook);
callback();
@ -184,6 +187,28 @@ module.exports = function (Plugins) {
}, callback);
}
function fireResponseHook(hook, hookList, params, callback) {
if (!Array.isArray(hookList) || !hookList.length) {
return callback();
}
async.eachSeries(hookList, function (hookObj, next) {
if (typeof hookObj.method !== 'function') {
if (global.env === 'development') {
winston.warn('[plugins] Expected method for hook \'' + hook + '\' in plugin \'' + hookObj.id + '\' not found, skipping.');
}
return next();
}
// Skip remaining hooks if headers have been sent
if (params.res.headersSent) {
return next();
}
hookObj.method(params);
next();
}, callback);
}
Plugins.hasListeners = function (hook) {
return !!(Plugins.loadedHooks[hook] && Plugins.loadedHooks[hook].length > 0);
};

Loading…
Cancel
Save