diff --git a/lib/http/base.js b/lib/http/base.js index 275a8d40..8900cae4 100644 --- a/lib/http/base.js +++ b/lib/http/base.js @@ -33,6 +33,7 @@ function HTTPBase(options) { this.io = null; this.routes = new Routes(); this.stack = []; + this.hooks = []; this._init(); } @@ -115,6 +116,9 @@ HTTPBase.prototype.handleRequest = co(function* handleRequest(req, res) { this.emit('request', req, res); + if (yield this.handleStack(req, res)) + return; + req.body = yield this.parseBody(req); routes = this.routes.getHandlers(req.method); @@ -131,7 +135,7 @@ HTTPBase.prototype.handleRequest = co(function* handleRequest(req, res) { req.params = params; - if (yield this.handleStack(req, res)) + if (yield this.handleHooks(req, res)) return; if (yield route.call(req, res)) @@ -174,30 +178,6 @@ HTTPBase.prototype.parseBody = co(function* parseBody(req) { return body; }); -/** - * Handle middleware stack. - * @private - * @param {HTTPRequest} req - * @param {HTTPResponse} res - * @returns {Promise} - */ - -HTTPBase.prototype.handleStack = co(function* handleStack(req, res) { - var i, route; - - for (i = 0; i < this.stack.length; i++) { - route = this.stack[i]; - - if (!route.hasPrefix(req.pathname)) - continue; - - if (yield route.call(req, res)) - return true; - } - - return false; -}); - /** * Read and buffer request body. * @param {ServerRequest} req @@ -241,8 +221,10 @@ HTTPBase.prototype._readBody = function _readBody(req, enc, resolve, reject) { req.removeListener('error', onError); req.removeListener('end', onEnd); - if (timer != null) + if (timer != null) { + timer = null; clearTimeout(timer); + } } function onData(data) { @@ -278,6 +260,54 @@ HTTPBase.prototype._readBody = function _readBody(req, enc, resolve, reject) { req.on('end', onEnd); }; +/** + * Handle middleware stack. + * @private + * @param {HTTPRequest} req + * @param {HTTPResponse} res + * @returns {Promise} + */ + +HTTPBase.prototype.handleStack = co(function* handleStack(req, res) { + var i, route; + + for (i = 0; i < this.stack.length; i++) { + route = this.stack[i]; + + if (!route.hasPrefix(req.pathname)) + continue; + + if (yield route.call(req, res)) + return true; + } + + return false; +}); + +/** + * Handle hook stack. + * @private + * @param {HTTPRequest} req + * @param {HTTPResponse} res + * @returns {Promise} + */ + +HTTPBase.prototype.handleHooks = co(function* handleHooks(req, res) { + var i, route; + + for (i = 0; i < this.hooks.length; i++) { + route = this.hooks[i]; + + if (!route.hasPrefix(req.pathname)) + continue; + + if (yield route.call(req, res)) + return true; + } + + return false; +}); + /** * Initialize websockets. * @private @@ -361,6 +391,21 @@ HTTPBase.prototype.use = function use(path, handler, ctx) { this.stack.push(new Route(ctx, path, handler)); }; +/** + * Add a hook to the stack. + * @param {String?} path + * @param {Function} handler + * @param {Object?} ctx + */ + +HTTPBase.prototype.hook = function hook(path, handler, ctx) { + if (!handler) { + handler = path; + path = null; + } + this.hooks.push(new Route(ctx, path, handler)); +}; + /** * Add a GET route. * @param {String} path diff --git a/lib/http/server.js b/lib/http/server.js index 8f68690f..1f62be37 100644 --- a/lib/http/server.js +++ b/lib/http/server.js @@ -173,7 +173,7 @@ HTTPServer.prototype._init = function _init() { res.send(401, { error: 'Bad API key.' }); })); - this.use(co(function* (req, res) { + this.hook(co(function* (req, res) { var i, params, options, censored, output, address; if (req.method === 'POST' && req.pathname === '/') { @@ -472,7 +472,7 @@ HTTPServer.prototype._init = function _init() { req.options = options; })); - this.use(co(function* (req, res) { + this.hook(co(function* (req, res) { var options = req.options; var wallet; @@ -1624,6 +1624,20 @@ HTTPServer.prototype.use = function use(path, handler) { return this.server.use(path, handler, this); }; +/** + * Add a hook to the stack. + * @param {String?} path + * @param {Function} handler + */ + +HTTPServer.prototype.hook = function hook(path, handler) { + if (!handler) { + handler = path; + path = null; + } + return this.server.hook(path, handler, this); +}; + /** * Add a GET route. * @param {String} path