it("returns the parsed body on success", async () => {
readJsonBodyMock.mockResolvedValueOnce({ ok: true, value: { hello: "world" } }); const { res } = makeMockHttpResponse(); const result = await readJsonBodyOrError(makeRequest(), res, 1024);
expect(result).toEqual({ hello: "world" });
expect(readJsonBodyMock).toHaveBeenCalledWith(expect.anything(), 1024);
});
it("responds with 413 when the body is too large", async () => {
readJsonBodyMock.mockResolvedValueOnce({ ok: false, error: "payload too large" }); const events: DiagnosticEventPayload[] = []; const stop = onDiagnosticEvent((event) => events.push(event)); const { res, end } = makeMockHttpResponse(); const req = { headers: { "content-length": "2048" } } as IncomingMessage; const result = await readJsonBodyOrError(req, res, 1024);
stop();
expect(result).toBeUndefined();
expect(res.statusCode).toBe(413);
expect(end).toHaveBeenCalledWith(
JSON.stringify({
error: { message: "Payload too large", type: "invalid_request_error" },
}),
);
expect(events).toContainEqual(
expect.objectContaining({
type: "payload.large",
surface: "gateway.http.json",
action: "rejected",
bytes: 2048,
limitBytes: 1024,
reason: "json_body_limit",
}),
);
});
it("responds with 408 when the request body times out", async () => {
readJsonBodyMock.mockResolvedValueOnce({ ok: false, error: "request body timeout" }); const { res, end } = makeMockHttpResponse(); const result = await readJsonBodyOrError(makeRequest(), res, 1024);
expect(result).toBeUndefined();
expect(res.statusCode).toBe(408);
expect(end).toHaveBeenCalledWith(
JSON.stringify({
error: { message: "Request body timeout", type: "invalid_request_error" },
}),
);
});
it("responds with 400 for other parse failures", async () => {
readJsonBodyMock.mockResolvedValueOnce({ ok: false, error: "bad json" }); const { res, end } = makeMockHttpResponse(); const result = await readJsonBodyOrError(makeRequest(), res, 1024);
expect(result).toBeUndefined();
expect(res.statusCode).toBe(400);
expect(end).toHaveBeenCalledWith(
JSON.stringify({ error: { message: "bad json", type: "invalid_request_error" } }),
);
});
});
describe("writeDone", () => {
it("writes the SSE termination sentinel to the response stream", () => { const { res } = makeMockHttpResponse(); const write = vi.spyOn(res, "write");
writeDone(res);
expect(write).toHaveBeenCalledWith("data: [DONE]\n\n");
});
});
describe("setSseHeaders", () => {
it("sets the SSE headers and calls flushHeaders when present", () => { const { res, setHeader } = makeMockHttpResponse(); const flushHeaders = vi.fn();
(res as unknown as { flushHeaders: () => void }).flushHeaders = flushHeaders;
setSseHeaders(res);
expect(res.statusCode).toBe(200);
expect(setHeader).toHaveBeenCalledWith("Content-Type", "text/event-stream; charset=utf-8");
expect(setHeader).toHaveBeenCalledWith("Cache-Control", "no-cache");
expect(setHeader).toHaveBeenCalledWith("Connection", "keep-alive");
expect(flushHeaders).toHaveBeenCalledTimes(1);
});
it("skips flushHeaders gracefully when the response does not expose one", () => { const { res, setHeader } = makeMockHttpResponse(); // Ensure flushHeaders is not defined on the mock response.
expect((res as unknown as { flushHeaders?: () => void }).flushHeaders).toBeUndefined();
expect(() => setSseHeaders(res)).not.toThrow();
expect(setHeader).toHaveBeenCalledWith("Content-Type", "text/event-stream; charset=utf-8");
});
});
describe("watchClientDisconnect", () => { function buildReqRes(
reqSocket: EventEmitter | null,
resSocket: EventEmitter | null,
): { req: IncomingMessage; res: ServerResponse } { return {
req: { socket: reqSocket } as unknown as IncomingMessage,
res: { socket: resSocket } as unknown as ServerResponse,
};
}
it("returns a no-op cleanup when no sockets are available", () => { const { req, res } = buildReqRes(null, null); const controller = new AbortController(); const cleanup = watchClientDisconnect(req, res, controller);
expect(typeof cleanup).toBe("function");
expect(() => cleanup()).not.toThrow();
expect(controller.signal.aborted).toBe(false);
});
it("aborts the controller and calls onDisconnect when a socket closes", () => { const socket = new EventEmitter(); const { req, res } = buildReqRes(socket, socket); const controller = new AbortController(); const onDisconnect = vi.fn();
watchClientDisconnect(req, res, controller, onDisconnect);
socket.emit("close");
expect(onDisconnect).toHaveBeenCalledTimes(1);
expect(controller.signal.aborted).toBe(true);
});
it("does not double-abort when the controller is already aborted", () => { const socket = new EventEmitter(); const { req, res } = buildReqRes(socket, null); const controller = new AbortController();
controller.abort(); const abortSpy = vi.spyOn(controller, "abort"); const onDisconnect = vi.fn();
watchClientDisconnect(req, res, controller, onDisconnect);
socket.emit("close");
expect(onDisconnect).toHaveBeenCalledTimes(1);
expect(abortSpy).not.toHaveBeenCalled();
});
it("works without an onDisconnect callback", () => { const socket = new EventEmitter(); const { req, res } = buildReqRes(null, socket); const controller = new AbortController();
watchClientDisconnect(req, res, controller);
socket.emit("close");
expect(controller.signal.aborted).toBe(true);
});
it("deduplicates identical request and response sockets", () => { const socket = new EventEmitter(); const onSpy = vi.spyOn(socket, "on"); const { req, res } = buildReqRes(socket, socket); const controller = new AbortController();
watchClientDisconnect(req, res, controller);
expect(onSpy).toHaveBeenCalledTimes(1);
});
it("registers handlers on distinct request and response sockets", () => { const reqSocket = new EventEmitter(); const resSocket = new EventEmitter(); const reqOn = vi.spyOn(reqSocket, "on"); const resOn = vi.spyOn(resSocket, "on"); const { req, res } = buildReqRes(reqSocket, resSocket); const controller = new AbortController();
watchClientDisconnect(req, res, controller);
expect(reqOn).toHaveBeenCalledWith("close", expect.any(Function));
expect(resOn).toHaveBeenCalledWith("close", expect.any(Function));
});
it("cleanup detaches the close listener from each socket", () => { const socket = new EventEmitter(); const { req, res } = buildReqRes(socket, null); const controller = new AbortController(); const cleanup = watchClientDisconnect(req, res, controller);
expect(socket.listenerCount("close")).toBe(1);
cleanup();
expect(socket.listenerCount("close")).toBe(0);
});
});
Messung V0.5 in Prozent
¤ Dauer der Verarbeitung: 0.18 Sekunden
(vorverarbeitet am 2026-06-10)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.