fix(proxy): isolate image-proxy rate limiter
Some checks failed
Lint / build (20) (push) Has been cancelled
Playwright Tests / test (push) Has been cancelled

This commit is contained in:
Your Name 2026-03-05 16:18:58 +08:00
parent 60349a3bb0
commit 326707064c
2 changed files with 17 additions and 0 deletions

View File

@ -80,6 +80,9 @@ export const rateLimiters = {
// 文件上传接口:每分钟60次请求(独立于通用API限流)
upload: new RateLimiter(60000, 60),
// 图片代理接口:每分钟3000次请求(图片列表/画布高频加载)
imageProxy: new RateLimiter(60000, 3000),
// 高频只读接口(首页/画布轮询):每分钟1200次请求
uiPolling: new RateLimiter(60000, 1200),

View File

@ -77,6 +77,20 @@ export async function proxy(request: NextRequest) {
{ status: 429 }
);
}
} else if (pathname === "/api/image-proxy" && request.method === "GET") {
const imageProxyRateLimit = checkRateLimit(request, rateLimiters.imageProxy);
if (!imageProxyRateLimit.allowed) {
const retryAfter = Math.max(1, Math.ceil((imageProxyRateLimit.resetTime - Date.now()) / 1000));
console.warn(`[Security] Image proxy rate limit exceeded for IP: ${clientIP}`, {
pathname,
method: request.method,
resetTime: new Date(imageProxyRateLimit.resetTime).toISOString(),
});
return NextResponse.json(
{ error: "Too many image proxy requests", retryAfter },
{ status: 429, headers: { "Retry-After": String(retryAfter) } }
);
}
} else if (pathname === "/api/files/upload" && request.method === "POST") {
const token = await resolveToken();
const userId =