Express-rate-limit 实现速率限制功能
使用 express-rate-limit
可以实现基本的速率限制功能,而不需要自己手动管理 Redis 或其他存储系统。express-rate-limit
提供了简单的速率限制中间件,可以根据 IP 地址、路由等对请求进行限制。
基本的使用方式
首先,我们需要安装 express-rate-limit
:
bash
npm install express-rate-limit
然后,在你的 Express 应用中配置 express-rate-limit
中间件来实现请求速率限制。
代码实现
js
import express from "express";
import rateLimit from "express-rate-limit";
const app = express();
// 设置基本的速率限制
const limiter = rateLimit({
windowMs: 60 * 1000, // 1分钟的时间窗口
max: 10, // 每个IP在1分钟内最多只能发出10个请求
message: "Too many requests from this IP, please try again later.", // 超过限制时返回的消息
statusCode: 429, // 超过限制时的HTTP状态码
handler: (req, res, next) => {
// 自定义处理逻辑(如果需要,可以记录日志等)
console.log(`Rate limit exceeded for IP: ${req.ip}`);
res.status(429).send({
code: 429,
status: "error",
message: "Too many requests from this IP, please try again later.",
});
},
skip: (req) => {
// 如果请求的 URL 是 `/public`,则跳过速率限制
return req.url.startsWith("/public");
},
});
// 在应用中使用速率限制中间件
app.use(limiter);
// 创建一个简单的路由
app.get("/", (req, res) => {
res.send("Hello, World!");
});
// 启动服务器
app.listen(3000, () => {
console.log("Server is running on port 3000");
});
请求超过 10 次后(1 分钟内),会返回如下错误:
解释
windowMs
:指定了限制的时间窗口(例如:1 分钟 =60 * 1000
毫秒)。max
:指定每个 IP 在windowMs
时间内最多可以发送的请求次数(例如:每个 IP 每分钟最多请求 10 次)。message
:超出请求限制时,客户端收到的错误消息。statusCode
:超出请求限制时返回的 HTTP 状态码(默认是 429)。handler
:超出限制时的自定义处理函数。在这里,你可以记录日志、通知管理员、或者做其他处理。
高级配置
除了基本的配置外,express-rate-limit
还支持更多的高级选项:
skip
:你可以设置一个条件来跳过速率限制,例如某些 IP 地址或某些路由。keyGenerator
:自定义速率限制的键(例如:使用请求的user_id
而不是IP
地址)。onLimitReached
:当达到请求限制时,执行某些操作。
例如,如果你想要对管理员用户进行更高的限制,或者跳过特定的请求,可以使用 skip
或 keyGenerator
来进行定制。
示例:跳过某些路由
js
const limiter = rateLimit({
windowMs: 60 * 1000, // 1分钟的时间窗口
max: 10, // 每个IP在1分钟内最多只能发出10个请求
message: "Too many requests from this IP, please try again later.",
statusCode: 429,
skip: (req) => {
// 如果请求的 URL 是 `/public`,则跳过速率限制
return req.url.startsWith("/public");
},
});
示例:自定义请求限制键
如果你想使用用户的 user_id
作为请求限制的键,而不是默认的 IP 地址,可以使用 keyGenerator
:
js
const limiter = rateLimit({
windowMs: 60 * 1000, // 1分钟时间窗口
max: 10, // 每个用户每分钟最多请求10次
keyGenerator: (req) => req.user.id, // 使用用户ID作为速率限制的键
message: "Too many requests from this user, please try again later.",
statusCode: 429,
});
总结
express-rate-limit
提供了一个简单、快速的方式来实现基本的速率限制功能。它不需要 Redis 或其他存储系统,适合于小到中型应用。- 对于大规模或分布式系统,可能需要将速率限制数据存储到 Redis 或类似的存储系统中,以确保不同服务器间的速率限制一致。
- 你可以根据需求自定义速率限制策略,例如按用户、IP 地址、路由等进行限制。