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

如何在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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.29 19:42:52