(
request: { headers: { get(name: string): string | null } },
scope: 'metadata' | 'content'
)
| 26 | * matching the chat public route. |
| 27 | */ |
| 28 | export async function enforcePublicFileRateLimit( |
| 29 | request: { headers: { get(name: string): string | null } }, |
| 30 | scope: 'metadata' | 'content' |
| 31 | ): Promise<NextResponse | null> { |
| 32 | const ip = getClientIp(request) |
| 33 | const config = scope === 'content' ? CONTENT_RATE_LIMIT : METADATA_RATE_LIMIT |
| 34 | const result = await rateLimiter.checkRateLimitDirect(`public-file:${scope}:${ip}`, config) |
| 35 | if (result.allowed) return null |
| 36 | |
| 37 | const headers = |
| 38 | result.retryAfterMs != null |
| 39 | ? { 'Retry-After': String(Math.ceil(result.retryAfterMs / 1000)) } |
| 40 | : undefined |
| 41 | return NextResponse.json( |
| 42 | { error: 'Too many requests. Please try again later.' }, |
| 43 | { status: 429, headers } |
| 44 | ) |
| 45 | } |
no test coverage detected