/** * POST /api/solve * * Returns a valid Cloudflare Turnstile token for geminigen.ai. * Protected by optional SOLVER_SECRET environment variable. * * Response: { token: string, cached: boolean, solvedInMs?: number } * Error: { error: string } */ import type { VercelRequest, VercelResponse } from "@vercel/node"; import { solveTurnstile, invalidateCache } from "../src/solver"; export default async function handler( req: VercelRequest, res: VercelResponse ) { // CORS preflight if (req.method === "OPTIONS") { return res.status(200).end(); } if (req.method !== "POST" && req.method !== "GET") { return res.status(405).json({ error: "Method not allowed" }); } // Optional secret check const secret = process.env.SOLVER_SECRET; if (secret) { const provided = req.headers["x-solver-secret"] || req.query.secret || req.body?.secret; if (provided !== secret) { return res.status(401).json({ error: "Unauthorized" }); } } // Force-invalidate cached token if requested if (req.query.force === "1" || req.body?.force) { invalidateCache(); } try { console.log("[solve] Starting Turnstile solve..."); const result = await solveTurnstile(); console.log( `[solve] Done — cached=${result.cached}, ms=${result.solvedInMs ?? 0}` ); return res.json(result); } catch (err: any) { console.error("[solve] Error:", err?.message); return res.status(500).json({ error: err?.message || "Solver failed" }); } }