From bb7c1aa1bd83694341035020e95f918fdbeb5fd1 Mon Sep 17 00:00:00 2001 From: Ralksta <16941050+ralksta@users.noreply.github.com> Date: Tue, 21 Apr 2026 22:51:42 +0200 Subject: [PATCH] Improve rate-limit headers in auth API (#102) Destructures `remaining` and `resetAt` from `checkRateLimit` and adds standard rate-limiting headers (`Retry-After`, `X-RateLimit-Limit`, `X-RateLimit-Remaining`) to the 429 Too Many Requests response. Co-authored-by: google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com> --- app/api/auth/route.ts | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/app/api/auth/route.ts b/app/api/auth/route.ts index 9e0d6a4..8e709a4 100644 --- a/app/api/auth/route.ts +++ b/app/api/auth/route.ts @@ -13,10 +13,20 @@ const AUTH_RPM = 10; export async function POST(request: NextRequest) { // ── Rate limiting (brute-force protection) ────────── const ip = getClientIp(request); - const { success } = checkRateLimit(`auth:${ip}`, AUTH_RPM); + const { success, remaining, resetAt } = checkRateLimit(`auth:${ip}`, AUTH_RPM); if (!success) { - return NextResponse.json({ error: 'Too many attempts, try again later' }, { status: 429 }); + return NextResponse.json( + { error: 'Too many attempts, try again later' }, + { + status: 429, + headers: { + 'Retry-After': String(Math.ceil((resetAt - Date.now()) / 1000)), + 'X-RateLimit-Limit': String(AUTH_RPM), + 'X-RateLimit-Remaining': String(remaining), + }, + }, + ); } try {