import { NextRequest, NextResponse } from "next/server"; export const runtime = "nodejs"; /** * 微信 CDN 图片代理(仅用于本地预览)。 * mmbiz.qpic.cn 有防盗链: 带非微信域名 Referer 会返回占位图。 * 服务端 fetch 默认不带 Referer, 可拿到真图。仅允许代理微信图片域名。 */ const ALLOWED_HOST_RE = /\.qpic\.cn$/; export async function GET(req: NextRequest) { const u = req.nextUrl.searchParams.get("u"); if (!u) return new NextResponse("missing u", { status: 400 }); let target: URL; try { target = new URL(u); } catch { return new NextResponse("bad url", { status: 400 }); } if (target.protocol !== "https:" || !ALLOWED_HOST_RE.test(target.hostname)) { return new NextResponse("host not allowed", { status: 403 }); } try { const upstream = await fetch(target.toString(), { headers: { "User-Agent": "Mozilla/5.0", Accept: "image/*" }, cache: "no-store", }); if (!upstream.ok || !upstream.body) { return new NextResponse("upstream error", { status: 502 }); } return new NextResponse(upstream.body, { status: 200, headers: { "Content-Type": upstream.headers.get("content-type") ?? "image/jpeg", "Cache-Control": "public, max-age=86400", }, }); } catch { return new NextResponse("fetch failed", { status: 502 }); } }