web/app/api/canopy/events/route.tsblame
View source
8d0dc121/**
8d0dc122 * Streaming SSE proxy for Canopy events.
8d0dc123 *
8d0dc124 * Next.js rewrites buffer responses, which breaks Server-Sent Events.
8d0dc125 * This route handler streams the SSE response directly from grove-api
8d0dc126 * to the browser without buffering.
8d0dc127 */
8d0dc128
8d0dc129const GROVE_API_URL = process.env.GROVE_API_URL ?? "http://localhost:4000";
8d0dc1210
8d0dc1211export const dynamic = "force-dynamic";
8d0dc1212
8d0dc1213export async function GET(request: Request) {
8d0dc1214 const { searchParams } = new URL(request.url);
8d0dc1215 const upstream = `${GROVE_API_URL}/api/canopy/events?${searchParams}`;
8d0dc1216
8d0dc1217 const res = await fetch(upstream, {
8d0dc1218 headers: {
8d0dc1219 Accept: "text/event-stream",
8d0dc1220 "Cache-Control": "no-cache",
8d0dc1221 },
8d0dc1222 signal: request.signal,
8d0dc1223 });
8d0dc1224
8d0dc1225 if (!res.ok || !res.body) {
8d0dc1226 return new Response("upstream error", { status: 502 });
8d0dc1227 }
8d0dc1228
8d0dc1229 return new Response(res.body, {
8d0dc1230 headers: {
8d0dc1231 "Content-Type": "text/event-stream",
8d0dc1232 "Cache-Control": "no-cache",
8d0dc1233 Connection: "keep-alive",
8d0dc1234 "X-Accel-Buffering": "no",
8d0dc1235 },
8d0dc1236 });
8d0dc1237}