You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

express-rate-limit为何对客户端发起的服务器请求不生效?

express-rate-limit 对客户端接口请求不生效的问题排查

我用React和JavaScript搭建了一个前后端分离的Web应用,在服务端的app.js里配置了express-rate-limit限流中间件:

require("./DB/connectToDb");
// require("./primeryData/primeryCards")();
const express = require("express");
const app = express();
const rateLimit = require("express-rate-limit");

const usersRouter = require("./Routes/Users/userRouter");
const cardsRouter = require("./Routes/Cards/cardsRouter");
const ordersRouter = require("./Routes/Orders/OrderRouter");

const chalk = require("chalk");
const morgan = require("morgan");
const cors = require("cors");

app.use(morgan(chalk.cyan(":method :url :status :response-time ms")));
app.use(cors());
app.use(express.json());
app.use("/api/users", usersRouter);
app.use("/api/cards", cardsRouter);
app.use("/api/orders", ordersRouter);

const PORT = 8181;
app.listen(PORT, () =>
  console.log(chalk.blueBright.bold(`server run on: http://:localhost:${PORT}`))
);

const limiter = rateLimit({
    windowMs: 15 * 60 * 1000, // 15 minutes
    max: 10, // Limit each IP to 100 requests per `window` (here, per 15 minutes)
    message: "Limited I Guess..."
})

app.get("/",limiter,(req,res)=>res.send(req.ip));


app.use('/api', limiter);

直接在浏览器访问http://localhost:8181/时,页面会显示我的IP(::1),刷新10次以上会触发限流提示"Limited I Guess...",符合预期。但通过客户端调用服务端的API接口时,却能无限制发起请求。想知道是不是漏了什么配置?express-rate-limit对客户端发起的请求到底有没有效?

以下是服务端API示例:

/********** Like/Dislike Card **********/

router.patch("/card-like/:id", auth, async (req, res) => {
  try {
    // console.log(req.params.id);
    const user = req.user;
    let card = await Card.findOne({ _id: req.params.id });

    const cardLikes = card.likes.find((id) => id === user._id);

    if (!cardLikes) {
      card.likes.push(user._id);
      card = await card.save();
      return res.send(card);
    }

    const cardFiltered = card.likes.filter((id) => id !== user._id);
    card.likes = cardFiltered;
    card = await card.save();
    return res.send(card);
  } catch (error) {
    console.log(chalk.redBright("Could not edit like:", error.message));
    return res.status(500).send(error.message);
  }
});

问题原因

核心问题是中间件挂载顺序错误:

  • 你先挂载了/api/users、/api/cards、/api/orders这些路由,之后才挂载app.use('/api', limiter)限流中间件。
  • Express的中间件和路由是按注册顺序匹配执行的,当请求命中前面的/api/*路由时,会直接进入对应路由处理逻辑并返回响应,后续的限流中间件根本不会被执行。

解决方法

调整代码顺序,把限流中间件的挂载移到所有/api前缀的路由之前:

require("./DB/connectToDb");
// require("./primeryData/primeryCards")();
const express = require("express");
const app = express();
const rateLimit = require("express-rate-limit");

const usersRouter = require("./Routes/Users/userRouter");
const cardsRouter = require("./Routes/Cards/cardsRouter");
const ordersRouter = require("./Routes/Orders/OrderRouter");

const chalk = require("chalk");
const morgan = require("morgan");
const cors = require("cors");

app.use(morgan(chalk.cyan(":method :url :status :response-time ms")));
app.use(cors());
app.use(express.json());

// 先注册/api前缀的限流中间件
const limiter = rateLimit({
    windowMs: 15 * 60 * 1000, // 15分钟
    max: 10, // 每个IP在15分钟内最多10次请求
    message: "Limited I Guess..."
});
app.use('/api', limiter);

// 再注册各个/api路由
app.use("/api/users", usersRouter);
app.use("/api/cards", cardsRouter);
app.use("/api/orders", ordersRouter);

const PORT = 8181;
// 建议把app.listen放在所有配置最后,结构更清晰
app.listen(PORT, () =>
  console.log(chalk.blueBright.bold(`server run on: http://localhost:${PORT}`))
);

app.get("/", limiter, (req, res) => res.send(req.ip));

补充说明

  • express-rate-limit对客户端发起的请求完全生效,只要中间件能被正确执行到。
  • 另外注意原代码中app.listen放在了中间件和路由注册之前,虽然不影响功能,但将其移到所有配置最后,代码结构会更清晰易维护。

内容的提问来源于stack exchange,提问作者Anonymous Op

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.24 08:54:20