Strapi自定义路由中express-rate-limit中间件未生效如何解决?
问题分析与解决方案
你的限流中间件未生效有两个核心原因:
- 执行顺序完全错误:你先调用了
await next(),这会直接把请求传递到后续路由处理逻辑,等请求处理完成后才创建限流实例——相当于请求已经处理完了才做限流检查,完全起不到限制作用。 - 中间件类型不兼容:
express-rate-limit是为Express框架设计的中间件,而Strapi基于Koa框架,两者的中间件模型不同,直接实例化无法适配Koa的上下文。
方案一:改用Koa生态的限流中间件(推荐)
使用koa-ratelimit(Koa官方生态的限流工具),适配性更好:
1. 依赖安装
npm install koa-ratelimit ioredis --save
(ioredis用于生产环境的持久化存储,开发环境可省略,改用内存存储)
2. 修正中间件代码
const RateLimit = require('koa-ratelimit'); const Redis = require('ioredis'); module.exports = () => { // 生产环境用Redis存储限流数据,避免重启服务后数据丢失 const redisStore = new Redis({ host: 'localhost', // 你的Redis地址 port: 6379 }); return RateLimit({ driver: 'redis', store: redisStore, duration: 60 * 1000, // 1分钟时间窗口 max: 3, // 每个IP最多3次请求 errorMessage: 'too many requests', id: (ctx) => ctx.ip, // 以请求IP作为限流标识 // 可选:添加限流响应头 headers: { remaining: 'X-RateLimit-Remaining', reset: 'X-RateLimit-Reset', total: 'X-RateLimit-Total' } }); };
如果是开发环境,可简化为内存存储:
const RateLimit = require('koa-ratelimit'); module.exports = () => { return RateLimit({ driver: 'memory', duration: 60 * 1000, max: 3, errorMessage: 'too many requests', id: (ctx) => ctx.ip }); };
方案二:适配express-rate-limit到Koa环境
如果坚持使用express-rate-limit,需要将其包装为Koa兼容的中间件:
1. 依赖安装
npm install koa-express-middleware --save
2. 修正中间件代码
const rateLimit = require("express-rate-limit"); const wrap = require('koa-express-middleware'); module.exports = () => { // 先创建Express限流中间件实例 const limiter = rateLimit({ windowMs: 60 * 1000, max: 3, message: "too many requests", }); // 包装为Koa中间件,并在请求处理前执行限流检查 return async (ctx, next) => { await wrap(limiter)(ctx, next); }; };
也可以手动适配(无需额外依赖):
const rateLimit = require("express-rate-limit"); module.exports = () => { const limiter = rateLimit({ windowMs: 60 * 1000, max: 3, message: "too many requests", }); return async (ctx, next) => { return new Promise((resolve, reject) => { // 将Koa上下文转换为Express兼容的req/res格式 limiter(ctx.req, ctx.res, (err) => { if (err) reject(err); else resolve(next()); }); }); }; };
最后确认
你的路由配置中中间件顺序是正确的(先验权再限流),修正中间件后重新启动Strapi,即可触发1分钟内超过3次请求时返回429错误及对应提示。
内容的提问来源于stack exchange,提问作者Mohsin Tariq
相关产品推荐
相关产品推荐

