背景#
限制一定时间内的 API 访问次数,比如一分钟内只允许访问 5 次 API。
方法#
注意:
- 通过在项目根目录创建
middleware.ts
(或 .js) 文件来定义 Middleware。例如,与 pages 或 app 位于同一级别,或在 src 中(如果适用)。 - 一个项目只支持一个 Middleware。
项目部署在 Vercel 环境#
如果项目部署在 Vercel 上,建议参考:Add Rate Limiting with Vercel Edge Middleware and Vercel KV
项目部署在非 Vercel 环境#
以下代码演示了:通过获取客户端 IP 来限制一分钟内最多访问 5 次 /api
开头的路由。
import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'
const rateLimitMap = new Map()
// This function can be marked `async` if using `await` inside
export function middleware(request: NextRequest) {
const ip = request.headers.get('x-forwarded-for') || request.ip
if (ip === '::1') return NextResponse.next()
const limit = 5 // Limiting requests to 5 per minute per IP
const windowMs = 60 * 1000 // 1 minute
if (!rateLimitMap.has(ip)) {
rateLimitMap.set(ip, {
count: 0,
lastReset: Date.now(),
})
}
const ipData = rateLimitMap.get(ip)
if (Date.now() - ipData.lastReset > windowMs) {
ipData.count = 0
ipData.lastReset = Date.now()
}
if (ipData.count >= limit) {
return NextResponse.json({ message: '请求太频繁,请 1 分钟后再试' }, { status: 429 })
}
ipData.count += 1
return NextResponse.next()
}
// See "Matching Paths" below to learn more
export const config = {
matcher: '/api/:path*',
}
代码源自:Implementing Rate Limiting in Next.js API Routes without External Packages