如何在Next.js 14 App Router中实现请求限流?
在Next.js 14 App Router中实现基于Express Rate Limit的限流
在Next.js 14的App Router中,路由处理器(Route Handlers)采用Web标准的Request/Response对象,而非Express的中间件模型,需要对express-rate-limit做简单适配才能使用。以下是具体实现步骤:
1. 安装依赖
首先安装核心限流包及可选的MongoDB存储适配包:
# 核心限流包 npm install express-rate-limit # 若需MongoDB存储(适配多实例部署),额外安装 npm install rate-limit-mongo
2. 封装限流适配函数
在项目中创建lib/rate-limit.ts文件,封装适配Next.js的限流逻辑:
import { rateLimit } from "express-rate-limit"; import { MongoStore } from "rate-limit-mongo"; import type { NextRequest } from "next/server"; import mongoose from "mongoose"; // 适配Next.js Request为Express兼容格式 const adaptRequest = (req: NextRequest) => ({ ip: req.ip || req.headers.get("x-forwarded-for") || "127.0.0.1", method: req.method, path: req.nextUrl.pathname, } as any); // 适配Express响应逻辑为Next.js Response const adaptResponse = () => { let statusCode = 200; const headers = new Headers(); return { status(code: number) { statusCode = code; return this; }, setHeader(name: string, value: string) { headers.set(name, value); return this; }, end() { return new Response("Too many requests, please try again later.", { status: statusCode, headers, }); }, } as any; }; // 连接MongoDB(若使用MongoDB存储) const connectMongo = async () => { if (!mongoose.connection.readyState) { await mongoose.connect(process.env.MONGODB_URI!); } }; // 创建限流实例 const limiter = rateLimit({ windowMs: 15 * 60 * 1000, // 15分钟窗口 max: 200, // 每个IP最多200次请求 standardHeaders: true, // 返回RateLimit相关响应头 legacyHeaders: false, // 禁用旧版X-RateLimit头 // 若使用内存存储(仅单实例场景),可注释以下MongoStore配置 store: new MongoStore({ async init() { await connectMongo(); }, collectionName: "rateLimits", // MongoDB存储集合名 expireTimeMs: 15 * 60 * 1000, // 数据过期时间 mongooseConnection: mongoose.connection, }), }); // 暴露给路由处理器使用的限流函数 export const applyRateLimit = async (req: NextRequest): Promise<Response | null> => { return new Promise((resolve) => { const adaptedReq = adaptRequest(req); const adaptedRes = adaptResponse(); limiter(adaptedReq, adaptedRes, (err) => { err ? resolve(adaptedRes.end()) : resolve(null); }); }); };
3. 在路由处理器中使用限流
在App Router的任意路由处理器(如app/api/[route]/route.ts)中引入并使用:
import { NextRequest, NextResponse } from "next/server"; import { applyRateLimit } from "@/lib/rate-limit"; export async function GET(req: NextRequest) { // 先执行限流检查 const rateLimitRes = await applyRateLimit(req); if (rateLimitRes) return rateLimitRes; // 正常业务逻辑 return NextResponse.json({ message: "Request successful" }); } // 其他请求方法(POST/PUT等)同样适用 export async function POST(req: NextRequest) { const rateLimitRes = await applyRateLimit(req); if (rateLimitRes) return rateLimitRes; // 业务逻辑 return NextResponse.json({ message: "Data created" }); }
关键注意事项
- IP获取准确性:若部署在Vercel、Netlify等平台,需开启
trustProxy配置(在rateLimit选项中添加trustProxy: true),确保能正确获取用户真实IP(通过x-forwarded-for头)。 - 存储方案选择:内存存储仅适合单实例部署,多实例场景必须使用MongoDB/Redis等分布式存储,避免限流规则失效。
内容的提问来源于stack exchange,提问作者soheil
相关产品推荐
相关产品推荐

