/* SPDX-FileCopyrightText: © 2025 Hornwitser SPDX-License-Identifier: AGPL-3.0-or-later */ import { pipeline } from "node:stream"; import { createEventStream } from "~/server/streams"; export default defineEventHandler(async (event) => { const session = await getServerSession(event, false); let lastEventId: number | undefined; const lastEventIdHeader = event.headers.get("Last-Event-ID"); const lastEventIdQuery = getQuery(event)["lastEventId"]; if (lastEventIdHeader) { if (!/^[0-9]{1,15}$/.test(lastEventIdHeader)) { throw createError({ statusCode: 400, statusMessage: "Bad Request", message: "Malformed Last-Event-ID header", }); } lastEventId = Number.parseInt(lastEventIdHeader, 10); } else if (lastEventIdQuery) { if (typeof lastEventIdQuery !== "string" || !/^[0-9]{1,15}$/.test(lastEventIdQuery)) { throw createError({ statusCode: 400, statusMessage: "Bad Request", message: "Malformed lastEventId", }); } lastEventId = Number.parseInt(lastEventIdQuery, 10); } else { throw createError({ statusCode: 400, statusMessage: "Bad Request", message: "lastEventId is required", }); } const source = event.headers.get("x-forwarded-for") ?? ""; const stream = await createEventStream(event, source, lastEventId, session); // Workaround to properly handle stream errors. See https://github.com/unjs/h3/issues/986 setHeader(event, "Access-Control-Allow-Origin", "*"); setHeader(event, "Content-Type", "text/event-stream"); pipeline(stream as unknown as NodeJS.ReadableStream, event.node.res, (err) => { /* ignore */ }); event._handled = true; });