import { NextResponse } from "next/server"; import { auth } from "@/app/(auth)/auth"; export const runtime = "nodejs"; export const maxDuration = 60; function isAllowedModelHost(hostname: string) { const normalized = hostname.toLowerCase(); return ( normalized === "tripo3d.com" || normalized.endsWith(".tripo3d.com") ); } export async function GET(request: Request) { try { const session = await auth(); if (!session?.user?.id) { return NextResponse.json({ success: false, error: "未登录" }, { status: 401 }); } const { searchParams } = new URL(request.url); const rawUrl = String(searchParams.get("url") || "").trim(); if (!rawUrl) { return NextResponse.json({ success: false, error: "缺少 url 参数" }, { status: 400 }); } let targetUrl: URL; try { targetUrl = new URL(rawUrl); } catch { return NextResponse.json({ success: false, error: "url 参数无效" }, { status: 400 }); } if (targetUrl.protocol !== "https:") { return NextResponse.json({ success: false, error: "仅支持 https 模型地址" }, { status: 400 }); } if (!isAllowedModelHost(targetUrl.hostname)) { return NextResponse.json({ success: false, error: "不允许的模型地址域名" }, { status: 403 }); } const forwardedHeaders = new Headers(); const range = request.headers.get("range"); if (range) { forwardedHeaders.set("range", range); } const upstream = await fetch(targetUrl.toString(), { method: "GET", headers: forwardedHeaders, cache: "no-store", }); if (!upstream.ok && upstream.status !== 206) { const upstreamText = await upstream.text().catch(() => ""); return NextResponse.json( { success: false, error: upstreamText || `模型拉取失败(HTTP ${upstream.status})`, }, { status: upstream.status || 502 } ); } const responseHeaders = new Headers(); const contentType = upstream.headers.get("content-type") || "application/octet-stream"; responseHeaders.set("content-type", contentType); const contentLength = upstream.headers.get("content-length"); if (contentLength) responseHeaders.set("content-length", contentLength); const contentRange = upstream.headers.get("content-range"); if (contentRange) responseHeaders.set("content-range", contentRange); const acceptRanges = upstream.headers.get("accept-ranges"); if (acceptRanges) responseHeaders.set("accept-ranges", acceptRanges); responseHeaders.set("cache-control", "private, no-store"); return new NextResponse(upstream.body, { status: upstream.status, headers: responseHeaders, }); } catch (error) { return NextResponse.json( { success: false, error: error instanceof Error ? error.message : "代理拉取 3D 模型失败", }, { status: 500 } ); } }