( bucketName: string, userId: string, config: TokenBucketConfig = DEFAULT_USER_ROUTE_LIMIT )
| 43 | * Returns a `NextResponse` on 429, otherwise `null` so the caller can proceed. |
| 44 | */ |
| 45 | export async function enforceUserRateLimit( |
| 46 | bucketName: string, |
| 47 | userId: string, |
| 48 | config: TokenBucketConfig = DEFAULT_USER_ROUTE_LIMIT |
| 49 | ): Promise<NextResponse | null> { |
| 50 | const key = `route:${bucketName}:user:${userId}` |
| 51 | const { allowed, resetAt } = await rateLimiter.checkRateLimitDirect(key, config) |
| 52 | if (allowed) return null |
| 53 | logger.warn('User rate limit exceeded', { bucket: bucketName, userId }) |
| 54 | return buildRateLimitResponse(resetAt) |
| 55 | } |
| 56 | |
| 57 | /** |
| 58 | * Apply a per-IP token bucket to an unauthenticated route. The `unknown` IP |
no test coverage detected