我使用的是Express (v4.17.3)、Socket.io和Node.js的http模块。我正在为express添加一个中间件来捕获所有传入请求,但这是失败的。
我将首先展示我使用的代码和输出,然后解释我对输出的理解/期望(我对Node和所有提到的库都是新手,所以我可能遗漏了什么)
首先,下面是我指的代码。使用Express的中间件,我试图捕获所有传入的请求并记录它们,并对http on("request")进行同样的记录。然而,发送到socket.io的请求不会被中间件捕获。
// Express
const express = require("express");
const app = express()
// Socket
const server = require('http').createServer(app);
const {Server} = require("socket.io");
const io = new Server(server)
// Want to listen to all incoming requests using the middleware (this doesn't work)
app.use((req,res,next)=>{
console.log(`Express request = ${req.url}`)
next()
})
// Listening to all incoming requests (this works)
server.on("request", (req, res)=>{
console.log(`Http request = ${req.url}`)
})
server.listen(8080, () => {
console.log(`Listening on port 8080`)
})当我得到/得到时输出
Express request = /
Http request = /
Http request = /socket.io/socket.io.js
Http request = /socket.io/?EIO=4&transport=polling&t=O0va...
Http request = /socket.io/?EIO=4&transport=polling&t=O0va24A&sid=c...
Http request = /socket.io/?EIO=4&transport=polling&t=O0va24F&sid=c...
Http request = /socket.io/?EIO=4&transport=polling&t=O0va27x&sid=c...我的预期输出是对中间件app.use()和on("request")具有相同的日志("Express请求=“& "Http请求")
我的理解:
1-当我为express添加中间件时(如下面的代码所示),任何传入的请求都应该先在这里捕获,然后再进入其他任何地方。(对吗?)
app.use((req,res,next)=>{...})
2-当我将快递应用程序作为参数传递给http的createServer时,快递应用程序将被视为侦听器,任何request事件都将传递给它。(对吗?)
const server = require('http').createServer(app);
因此,如果我的理解是正确的,为什么请求事件捕获的所有请求也不传递给中间件?
发布于 2022-04-17 22:53:45
这很正常。Socket.io将自己置于express (或http服务器上任何其他传入请求的侦听器)前面,以便在Express看到请求之前接受它。因此,Express (或它的中间件)从未看到任何socket.io连接请求。
Socket.io有它的自己的中间件层,您可以使用它来参与socket.io请求的初始化。
或者,您可以向socket.io事件处理程序注册传入的io.on('connection', ...)连接(在它们已经连接之后将被调用)。
当我为express添加中间件时,如下面的代码所示,任何传入的请求都应该先在这里捕获,然后再进入其他任何地方。(对吗?)
除了直接在http服务器上注册请求处理程序并在侦听器链中的Express之前插入自身的代码之外,这是正确的,从而防止Express看到任何指向socket.io的请求。
当我将express应用程序作为参数传递给http‘’screateServer时,它将被视为侦听器,任何请求事件都将传递给它。(对吗?)
那是真的。但是socket.io跳到了Express前面,接收/隐藏它想要的任何请求,这样Express就不会看到它们。
如果您好奇的话,下面是跳到http服务器所有侦听器前面的socket.io代码,从而绕过了express侦听器:
attachServe(srv) {
debug("attaching client serving req handler");
const evs = srv.listeners("request").slice(0);
srv.removeAllListeners("request");
srv.on("request", (req, res) => {
if (this.clientPathRegex.test(req.url)) {
this.serve(req, res);
}
else {
for (let i = 0; i < evs.length; i++) {
evs[i].call(srv, req, res);
}
}
});
}它将所有现有的侦听器捕获到一个数组中。然后,它把它们全部移除。然后,它为request事件本身注册,如果它是一个socket.io请求,那么它不会调用先前的侦听器。如果它不是socket.io前缀,则手动调用前面的侦听器。
https://stackoverflow.com/questions/71905965
复制相似问题