fix: split gemini-token into GET health check + POST token request
All checks were successful
Build & Push / build-and-push (push) Successful in 1m33s
All checks were successful
Build & Push / build-and-push (push) Successful in 1m33s
Health check no longer triggers rate limiter, fixing toggle not appearing. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -4,9 +4,18 @@ import { generateEphemeralToken } from '@/lib/gemini-live';
|
|||||||
// ─── Rate Limiting ────────────────────────────────────────────────────────────
|
// ─── Rate Limiting ────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
const rateLimitMap = new Map<string, number>();
|
const rateLimitMap = new Map<string, number>();
|
||||||
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) {
|
export async function POST(request: NextRequest) {
|
||||||
try {
|
try {
|
||||||
@@ -26,12 +35,10 @@ export async function POST(request: NextRequest) {
|
|||||||
rateLimitMap.set(ip, Date.now());
|
rateLimitMap.set(ip, Date.now());
|
||||||
|
|
||||||
const { locale } = (await request.json()) as { locale?: string };
|
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({
|
return NextResponse.json({
|
||||||
success: true,
|
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,
|
apiKey: process.env.GEMINI_API_KEY,
|
||||||
model: result.model,
|
model: result.model,
|
||||||
config: result.config,
|
config: result.config,
|
||||||
|
|||||||
@@ -24,11 +24,7 @@ export default function ModeToggle({ mode, onChange }: ModeToggleProps) {
|
|||||||
if (!navigator.mediaDevices?.getUserMedia) return;
|
if (!navigator.mediaDevices?.getUserMedia) return;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const res = await fetch('/api/gemini-token', {
|
const res = await fetch('/api/gemini-token');
|
||||||
method: 'POST',
|
|
||||||
headers: { 'Content-Type': 'application/json' },
|
|
||||||
body: JSON.stringify({ locale: 'en' }),
|
|
||||||
});
|
|
||||||
const data = (await res.json()) as { success: boolean };
|
const data = (await res.json()) as { success: boolean };
|
||||||
if (data.success) setVoiceSupported(true);
|
if (data.success) setVoiceSupported(true);
|
||||||
} catch {
|
} catch {
|
||||||
|
|||||||
Reference in New Issue
Block a user