23882ac1ef
- web/sse_manager.py: asyncio.Queue 连接池 + broadcast + event_stream - web/routers/sse_router.py: GET /api/events + POST /api/internal/collector-patch - weather_sources.py: 采集后 POST patch 给 web - Nginx polyweather.conf: /api/events proxy_buffering off - frontend/api/events/route.ts: Next.js SSE 代理 - frontend/hooks/use-sse-patches.ts: EventSource + useLatestPatch + 重连 - LiveTemperatureThresholdChart: mergePatchIntoHourly 增量合并 - scan-terminal-query: 接入 SSE patch 更新行数据 - 新增 ssePatchArchitecture.test.ts 架构测试
41 lines
1.0 KiB
TypeScript
41 lines
1.0 KiB
TypeScript
import { NextRequest, NextResponse } from "next/server";
|
|
|
|
const API_BASE = process.env.POLYWEATHER_API_BASE_URL;
|
|
|
|
export const dynamic = "force-dynamic";
|
|
export const runtime = "nodejs";
|
|
|
|
export async function GET(req: NextRequest) {
|
|
if (!API_BASE) {
|
|
return NextResponse.json(
|
|
{ error: "POLYWEATHER_API_BASE_URL is not configured" },
|
|
{ status: 500 },
|
|
);
|
|
}
|
|
|
|
const upstream = await fetch(`${API_BASE.replace(/\/+$/, "")}/api/events`, {
|
|
cache: "no-store",
|
|
headers: {
|
|
Accept: "text/event-stream",
|
|
Cookie: req.headers.get("cookie") || "",
|
|
},
|
|
});
|
|
|
|
if (!upstream.ok || !upstream.body) {
|
|
return NextResponse.json(
|
|
{ error: `SSE upstream failed with HTTP ${upstream.status}` },
|
|
{ status: upstream.status || 502 },
|
|
);
|
|
}
|
|
|
|
return new Response(upstream.body, {
|
|
status: 200,
|
|
headers: {
|
|
"Content-Type": "text/event-stream",
|
|
"Cache-Control": "no-cache, no-transform",
|
|
Connection: "keep-alive",
|
|
"X-Accel-Buffering": "no",
|
|
},
|
|
});
|
|
}
|