import { NextRequest, NextResponse } from "next/server"; import { checkRateLimit, clientKeyFromHeaders, tryAcquireInspection } from "@/lib/inspect/admission"; import { inspectHost } from "@/lib/inspect/inspect"; import { InspectionInputError, InspectionPolicyError, InspectionResolutionError } from "@/lib/inspect/policy"; export const runtime = "nodejs"; export const dynamic = "force-dynamic"; function jsonError(error: string, status: number, headers: Record = {}) { return NextResponse.json({ error }, { status, headers: { "Cache-Control": "no-store", ...headers } }); } export function classifyInspectionError(error: unknown) { if (error instanceof InspectionInputError || error instanceof InspectionPolicyError) return { status: 400, message: error.message }; if (error instanceof InspectionResolutionError) return { status: 422, message: error.message }; return { status: 500, message: "Inspection service is temporarily unavailable. Try again shortly." }; } export async function GET(request: NextRequest) { const host = request.nextUrl.searchParams.get("host") ?? ""; const rate = checkRateLimit(clientKeyFromHeaders(request.headers)); if (!rate.allowed) return jsonError("Request rate limit reached. Try again shortly.", 429, { "Retry-After": String(rate.retryAfterSeconds) }); const release = tryAcquireInspection(); if (!release) { return jsonError("Inspection capacity is temporarily full. Try again shortly.", 429, { "Retry-After": "1" }); } try { return NextResponse.json(await inspectHost(host), { headers: { "Cache-Control": "no-store" } }); } catch (error) { const classified = classifyInspectionError(error); if (classified.status === 500) console.error("inspection_unexpected_error", { name: error instanceof Error ? error.name : "UnknownError", code: typeof error === "object" && error !== null && "code" in error ? String((error as { code?: unknown }).code ?? "") : "", }); return jsonError(classified.message, classified.status); } finally { release(); } }