我正在使用socket.io并使用rate-limiter-flexible和limiter来限制请求速率,但是我注意到/socket.io路由没有从任何一个接收到429,实际上,我可以不会使用app.use('/socket.io')..
我认为socket.io正在这条路线的后台进行一些处理,对吗?如果是这样,我如何确保在达到限制后向/socket.io发出的请求也收到429?
连接上的速率限制器:
this.io.on(this.SocketConstants.CONNECTION, async (client) => {
this.client = client;
try {
await this.rateLimiter.consume(client.handshake.address);
} catch (rejRes) {
// On flood
client.error('Too many requests');
client.disconnect(true);
}
http服务器上的速率限制器:
class RateLimiting {
constructor() {
this.limiter = new RateLimiter(2, 'minute', true);
this.index = this.index.bind(this);
}
index(req,res,next){
try {
this.limiter.removeTokens(1, function(err, remainingRequests) {
if (remainingRequests < 1) {
res.writeHead(429, {'Content-Type': 'text/plain;charset=UTF-8'});
res.end('429 Too Many Requests - your IP is being rate limited');
// res.status(429).json({ message: 'Too many requests' });
} else {
next();
}
});
}
catch(err){
console.log('Error', err);
}
}
}
对于任何有类似问题的人,我最终都尝试了几种不同的方法来实现这一目标,并且是最简单的方法:
AllowRequest是通过/失败功能,可用于覆盖默认的“ checkRequest”功能(reference here)
checkBucket(err, remainingRequests) {
remainingRequests < 1 ? false : true;
}
allowRequest(req, callback) {
const limit = this.limiter.removeTokens(1, this.checkBucket);
callback(limit ? null : 'Too many requests', limit);
}
服务器启动为
this.io = this.socketServer(server,
{
allowRequest: this.allowRequest
});
您可以通过将serveClient
设置为false并将path
设置为所需的值来实现。
this.io = this.socketServer(服务器, { 路径:“ / newSocketRoute”, serveClient:否 });
这对我来说不太奏效,所以我提供套接字文件的方式可能出了点问题,但这是这样的:
app.get("/socket", this.limiter.initialize(), function(req, res) {
if (0 === req.url.indexOf('/newSocketRoute/socket.io.js.map')) {
res.sendFile(join(__dirname, "../../node_modules/socket.io-client/dist/socket.io.js.map"));
} else if (0 === req.url.indexOf('/newSocketRoute/socket.io.js')) {
res.sendFile(join(__dirname, "../../node_modules/socket.io-client/dist/socket.io.js"));
}
});
答案 0 :(得分:0)
Socket.io通过将自身作为第一个request
事件(socket.io代码reference here)的侦听器插入到HTTP服务器,这意味着它完全绕开了任何Express中间件。
如果您尝试将限制请求的速率分级为/socket.io/socket.io.js
(客户端socket.io代码),则可以使用自己的具有不同路径的自定义路由器在Express中为该文件创建自己的路由并让您的客户端仅使用路径的Express版本,然后可以通过socket.io禁用该文件的服务(可以选择禁用该文件)。
如果您想对传入的socket.io连接进行速率限制,则可能必须修改速率限制器,使其可以参与socket.io connect事件。
现在我想起来了,您可以像socket.io一样入侵request
事件侦听器列表(您可以看到上面引用的代码链接以了解其操作方式),并且可以插入自己的速率在看到请求之前进行限制。 socket.io所做的是实现一个穷人的中间件,并切入了代码的最前端,这样他们就可以在任何传入的http请求中首先破解,并在他们处理后将其隐藏。您可以使用速率限制器执行相同的操作。然后,您将参加一场“军备竞赛”,看看谁先破门而入。就个人而言,如果违反速率限制规则,我可能只是钩住connect
事件并在那里终止连接。但是,您可以破解并掌握socket.io代码。