From b4a265077ecaa297770d72ae2d07ae3d708dd8ac Mon Sep 17 00:00:00 2001 From: Matt Date: Sat, 28 Mar 2026 14:02:06 +0100 Subject: [PATCH] fix: split gemini-token into GET health check + POST token request Health check no longer triggers rate limiter, fixing toggle not appearing. Co-Authored-By: Claude Opus 4.6 (1M context) --- src/app/(frontend)/api/gemini-token/route.ts | 17 ++++++++++++----- src/components/configurator/ModeToggle.tsx | 6 +----- 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/src/app/(frontend)/api/gemini-token/route.ts b/src/app/(frontend)/api/gemini-token/route.ts index 12fd6da..46c4981 100644 --- a/src/app/(frontend)/api/gemini-token/route.ts +++ b/src/app/(frontend)/api/gemini-token/route.ts @@ -4,9 +4,18 @@ import { generateEphemeralToken } from '@/lib/gemini-live'; // ─── Rate Limiting ──────────────────────────────────────────────────────────── const rateLimitMap = new Map(); -const RATE_LIMIT_MS = 60_000; // 1 token per minute per IP +const RATE_LIMIT_MS = 30_000; // 1 token per 30 seconds per IP -// ─── Route Handler ──────────────────────────────────────────────────────────── +// ─── Health Check (GET — no rate limit) ────────────────────────────────────── + +export async function GET() { + if (!process.env.GEMINI_API_KEY) { + return NextResponse.json({ success: false }, { status: 503 }); + } + return NextResponse.json({ success: true }); +} + +// ─── Token Request (POST — rate limited) ───────────────────────────────────── export async function POST(request: NextRequest) { try { @@ -26,12 +35,10 @@ export async function POST(request: NextRequest) { rateLimitMap.set(ip, Date.now()); const { locale } = (await request.json()) as { locale?: string }; - const result = await generateEphemeralToken(locale === 'fr' ? 'fr' : 'en'); + const result = generateEphemeralToken(locale === 'fr' ? 'fr' : 'en'); return NextResponse.json({ success: true, - // In production, replace apiKey with an ephemeral token from ai.auth.tokens.create() - // to avoid exposing the long-lived API key to the client. apiKey: process.env.GEMINI_API_KEY, model: result.model, config: result.config, diff --git a/src/components/configurator/ModeToggle.tsx b/src/components/configurator/ModeToggle.tsx index 9008d11..bbc45ba 100644 --- a/src/components/configurator/ModeToggle.tsx +++ b/src/components/configurator/ModeToggle.tsx @@ -24,11 +24,7 @@ export default function ModeToggle({ mode, onChange }: ModeToggleProps) { if (!navigator.mediaDevices?.getUserMedia) return; try { - const res = await fetch('/api/gemini-token', { - method: 'POST', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ locale: 'en' }), - }); + const res = await fetch('/api/gemini-token'); const data = (await res.json()) as { success: boolean }; if (data.success) setVoiceSupported(true); } catch {