← back to Govarbitrage

src/app/api/import/url/route.ts

31 lines

import { NextRequest, NextResponse } from "next/server";
import { scrapeUrl } from "@/importers/scrape";
import { ingest } from "@/importers/ingest";
import { requireWrite } from "@/lib/auth";
import { assertPublicUrl } from "@/lib/ssrf-guard";

export const dynamic = "force-dynamic";
export const runtime = "nodejs";
export const maxDuration = 60;

// Scrape a single auction URL (Playwright best-effort) and ingest it.
export async function POST(req: NextRequest) {
  const denied = await requireWrite(req);
  if (denied) return denied;
  try {
    const { url } = (await req.json()) as { url?: string };
    if (!url) return NextResponse.json({ error: "Missing url" }, { status: 400 });
    // SSRF guard: reject metadata/loopback/private targets before scraping.
    try {
      await assertPublicUrl(url);
    } catch {
      return NextResponse.json({ error: "URL not allowed" }, { status: 400 });
    }
    const raw = await scrapeUrl(url);
    const result = await ingest(raw);
    return NextResponse.json({ ...result, raw });
  } catch (e) {
    return NextResponse.json({ error: (e as Error).message }, { status: 500 });
  }
}