将请求发送到NodeJS中的下一个事件处理程序

时间:2016-07-07 03:16:06

标签: node.js

我正在尝试创建一个模块,可以为请求记录某些某些参数并将其打印到可以在线检查的页面,该页面将使用socket.io加载最新的日志。

我希望这个模块可以作为一个插件工作,这意味着你只需要调用这个模块,并初始化它,然后一个额外的入口点/_logger将被添加到你的应用程序,一旦你访问该页面,最新日志将实时更新。因此模块必须拦截请求:

function setup(httpServer) {
    //page
    httpServer.on("request", function (request, response) {
        var pathname = url.parse(request.url).pathname;
        if (pathname === '/_logger') {
            fs.readFile(__dirname + '/logger.html', (err, data) => {
                response.writeHead(200, { 'Content-Type': 'text/html' });
                response.write(data);
                response.end();
            });
        }else{
          // how to give up the control for this requset
        }
    });


    var io = require('socket.io')(httpServer);
    io.on('connection', function (socket) {
        //TO BE DONE
        socket.on('event', function (data) { });
        socket.on('disconnect', function () { });
    });
}
module.exports = {
    setup: setup
}

用法:

var logger= require("./logger/index");
var server = require('http').createServer();
logger.setup(server);
server.on("request", function(req,res){
  //Normal logic for different application
});
server.listen(3333);

现在的问题是,一旦请求的网址不是/_logger,我就应该释放对此请求的控制权。

        if (pathname === '/_logger') {
          //take control
        }else{
          // Nothing should be done here, it should go to the next request chain.
        }

阅读完文件后,我找不到正确的方法。

有什么想法吗?

2 个答案:

答案 0 :(得分:1)

假设您要使用低级NodeJS HTTP API。您可以使用函数组合将多个处理程序组合成一个处理程序。如果req.url不匹配,则每个处理程序都应该执行下一个处理程序。

var http = require('http');

var handler1 = function(req, res) {
    res.writeHead(200, { 'Content-Type': 'text/html' });
    res.write('/');
    res.end();  
}

var handler2 = function(req, res) {
    res.writeHead(200, { 'Content-Type': 'text/html' });
    res.write('/Hello');
    res.end();  
}

var middleware = compose([wrapHandler('/', handler1),
                         wrapHandler('/hello', handler2)]);

http.createServer(middleware).listen(3000);

function wrapHandler(path, cb) {
    return function (req, res, next) {
        if (req.url === path) {
            cb(req, res);
        } else {
            next();
        }
    };
}

function notFoundHandler(req, res) {
    res.writeHead(404, { 'Content-Type': 'text/html' });
    res.write('No Path found');
    res.end();    
};

// adapted from koa-compose
function compose(middleware) {
    return function (req, res){
        let next = function () {
            notFoundHandler.call(this, req, res);
        };

        let i = middleware.length;
        while (i--) {
            let thisMiddleware = middleware[i];
            let nextMiddleware = next;
            next = function () { 
                thisMiddleware.call(this, req, res, nextMiddleware);
            }
        }
        return next();
    }
}

在你的情况下,你可以写。

var loggerHandler = wrapHandler('/_logger', logger.handler);
httpServer.on('request', compose(loggerHandler, handler2, handler3));

答案 1 :(得分:1)

httpServer.on("request", ...)只是一个请求侦听器。如果不需要,它没有义务处理请求。即使它什么都不做,任何其他请求监听器仍会收到此请求的通知。

如果有其他请求侦听器(您暗示有),那么您可以在您显示的请求侦听器中不执行任何操作,其他侦听器也将获取特定请求的镜头。这允许您将自己的请求侦听器添加到工作的http服务器,并且您的侦听器只需要关注它想要支持的新路由,并且可以忽略所有其他路由,并且它们将由其他侦听器处理。已经到位。

现在,有一些框架可以使这个更简单,并为您提供更多控制。通常,这些框架使用一个侦听器,它们为您提供处理请求的方法,或者明确告诉框架您没有处理请求,并希望其他路由处理程序能够处理请求。这比仅拥有多个侦听器更灵活,所有侦听器都会收到相同路由的通知。

例如,使用Express框架,您可以执行以下操作:

var express = require('express');
var app = express();

// route handler for / request only when a user=xxx is in the query string
app.get('/', function(req, res, next) {
    // if user was included in query parameter
    if (req.query.user) {
        // do something specific when ?user=xxxx is included in the URL
    } else {
        // pass handling to the next request handler in the chain
        next();
    }
});

// route handler for / request that wasn't already handled
app.get('/', function(req, res) {
    // handle the / route here
});

app.listen(80);