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

Node.js 将请求发送到NodeJS中的下一个事件处理程序,node.js,Node.js,我正在尝试创建一个模块,该模块可以记录请求的某些参数,并将它们打印到可以在线检查的页面,该页面将使用socket.io加载最新的日志 我希望这个模块可以作为一个插件工作,这意味着你只需调用这个模块,并初始化它,然后一个额外的入口点/\u logger将添加到你的应用程序中,一旦你访问页面,最新的日志将实时更新。因此,模块必须拦截请求: function setup(httpServer) { //page httpServer.on("request", function (re

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

我希望这个模块可以作为一个插件工作,这意味着你只需调用这个模块,并初始化它,然后一个额外的入口点
/\u 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);
现在的问题是,一旦请求的url不是
/\u logger
,我就应该释放对该请求的控制

        if (pathname === '/_logger') {
          //take control
        }else{
          // Nothing should be done here, it should go to the next request chain.
        }
看完文件后,我找不到正确的方法


有什么想法吗?

假设您想使用低级别的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));

假设您想要使用低级别的nodejshttpapi。可以使用函数组合将多个处理程序组合成一个处理程序。如果
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));
httpServer.on(“请求”,…)
只是一个请求侦听器。如果不需要,它没有义务处理请求。即使它什么也不做,任何其他请求侦听器仍将收到此请求的通知

        if (pathname === '/_logger') {
          //take control
        }else{
          // Nothing should be done here, it should go to the next request chain.
        }
如果有其他请求侦听器(您暗示有),那么您可以在您显示的请求侦听器中什么都不做,其他侦听器也将获得特定请求的快照。这允许您将自己的请求侦听器添加到正在工作的http服务器,并且您的侦听器只需关注它想要支持的新路由,就可以忽略所有其他路由,它们将由已经就位的其他侦听器处理


现在,已经构建了一些框架来简化这一过程,并为您提供更多的控制。通常,这些框架使用一个侦听器,它们为您处理请求提供了一种方法,或者显式地告诉框架您尚未处理请求,并且希望其他路由处理程序能够尝试处理请求。这比只有多个侦听器要灵活一些,所有侦听器都会收到相同路由的通知

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

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);
httpServer.on(“请求”,…)
只是一个请求侦听器。如果不需要,它没有义务处理请求。即使它什么也不做,任何其他请求侦听器仍将收到此请求的通知

        if (pathname === '/_logger') {
          //take control
        }else{
          // Nothing should be done here, it should go to the next request chain.
        }
如果有其他请求侦听器(您暗示有),那么您可以在您显示的请求侦听器中什么都不做,其他侦听器也将获得特定请求的快照。这允许您将自己的请求侦听器添加到正在工作的http服务器,并且您的侦听器只需关注它想要支持的新路由,就可以忽略所有其他路由,它们将由已经就位的其他侦听器处理


现在,已经构建了一些框架来简化这一过程,并为您提供更多的控制。通常,这些框架使用一个侦听器,它们为您处理请求提供了一种方法,或者显式地告诉框架您尚未处理请求,并且希望其他路由处理程序能够尝试处理请求。这比只有多个侦听器要灵活一些,所有侦听器都会收到相同路由的通知

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

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);

但是,我不能假设所有可能使用
logger
模块的应用程序都是基于express、connect或其他东西构建的。而且,正如您所提到的,在我的示例中,一个侦听器如果不需要做什么,就什么也做不了,在
请求
事件中添加了两个侦听器,一个是应用程序,另一个是
记录器
模块,因此每个请求都将首先由
记录器
处理,然后由应用程序处理,一旦请求的url是
\u记录器
,应用程序处理程序仍被调用,这将导致错误
write after end
@hguser-您没有完全解释您正在使用的限制。我只是解释一个真正的框架如何将请求从一个处理程序传递到下一个处理程序。如果您没有访问这样一个框架的权限,那么您所能做的就是像以前一样添加一个侦听器,如果请求与您的路由匹配,则处理请求,如果不匹配,则什么也不做。没有通用的方法“钩住”其他http服务器侦听器。这就是像Express这样的请求框架所提供的。普通http对象不提供该功能。@hguser-http模块本身不提供跳过其他服务器侦听器的方法。您必须找到一种不同的方式来钩住与您试图修补的应用程序兼容的请求。您没有向我们展示其他应用程序,因此我们很难知道如何制作与之兼容的东西。
没有通用的方法“挂钩”到其他http服务器侦听器
如果是这样,我就知道了。我可以使用由
zeronone
提供的解决方案来创建我自己的侦听器链。但我不能假设所有可能使用
logger
模块的应用程序都是基于express、connect或其他东西构建的。而且,正如您所提到的,在我的示例中,一个侦听器如果不需要做什么,就什么也做不了,在
请求
事件中添加了两个侦听器,一个是应用程序,另一个是
记录器
模块,因此每个请求都将首先由
记录器
处理