Skip to content

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

An image

请求超过 10 次后(1 分钟内),会返回如下错误:

An image

解释

  1. windowMs:指定了限制的时间窗口(例如:1 分钟 = 60 * 1000 毫秒)。
  2. max:指定每个 IP 在 windowMs 时间内最多可以发送的请求次数(例如:每个 IP 每分钟最多请求 10 次)。
  3. message:超出请求限制时,客户端收到的错误消息。
  4. statusCode:超出请求限制时返回的 HTTP 状态码(默认是 429)。
  5. handler:超出限制时的自定义处理函数。在这里,你可以记录日志、通知管理员、或者做其他处理。

高级配置

除了基本的配置外,express-rate-limit 还支持更多的高级选项:

  • skip:你可以设置一个条件来跳过速率限制,例如某些 IP 地址或某些路由。
  • keyGenerator:自定义速率限制的键(例如:使用请求的 user_id 而不是 IP 地址)。
  • onLimitReached:当达到请求限制时,执行某些操作。

例如,如果你想要对管理员用户进行更高的限制,或者跳过特定的请求,可以使用 skipkeyGenerator 来进行定制。

示例:跳过某些路由

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 地址、路由等进行限制。