From ed614938d7d1c04ad65bcd8e3bd92c65e49d1d3f Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Mon, 23 Mar 2026 06:37:14 +0000 Subject: [PATCH] test(voice-call): accept oversize webhook socket resets --- extensions/voice-call/src/webhook.test.ts | 55 +++++++++++++++++++++-- 1 file changed, 52 insertions(+), 3 deletions(-) diff --git a/extensions/voice-call/src/webhook.test.ts b/extensions/voice-call/src/webhook.test.ts index 004ba68a22f..f87193c7cd4 100644 --- a/extensions/voice-call/src/webhook.test.ts +++ b/extensions/voice-call/src/webhook.test.ts @@ -1,3 +1,4 @@ +import { request } from "node:http"; import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; import { VoiceCallConfigSchema, type VoiceCallConfig } from "./config.js"; import type { CallManager } from "./manager.js"; @@ -131,6 +132,50 @@ async function postWebhookFormWithHeaders( }); } +async function postWebhookFormWithHeadersResult( + server: VoiceCallWebhookServer, + baseUrl: string, + body: string, + headers: Record, +): Promise< + | { kind: "response"; statusCode: number; body: string } + | { kind: "error"; code: string | undefined } +> { + const requestUrl = requireBoundRequestUrl(server, baseUrl); + return await new Promise((resolve) => { + const req = request( + { + hostname: requestUrl.hostname, + port: requestUrl.port, + path: requestUrl.pathname + requestUrl.search, + method: "POST", + headers: { + "content-type": "application/x-www-form-urlencoded", + ...headers, + }, + }, + (res) => { + res.setEncoding("utf8"); + let responseBody = ""; + res.on("data", (chunk) => { + responseBody += chunk; + }); + res.on("end", () => { + resolve({ + kind: "response", + statusCode: res.statusCode ?? 0, + body: responseBody, + }); + }); + }, + ); + req.on("error", (error: NodeJS.ErrnoException) => { + resolve({ kind: "error", code: error.code }); + }); + req.end(body); + }); +} + describe("VoiceCallWebhookServer stale call reaper", () => { beforeEach(() => { vi.useFakeTimers(); @@ -363,15 +408,19 @@ describe("VoiceCallWebhookServer pre-auth webhook guards", () => { try { const baseUrl = await server.start(); - const response = await postWebhookFormWithHeaders( + const responseOrError = await postWebhookFormWithHeadersResult( server, baseUrl, "CallSid=CA123&SpeechResult=".padEnd(70 * 1024, "a"), { "x-twilio-signature": "sig" }, ); - expect(response.status).toBe(413); - expect(await response.text()).toBe("Payload Too Large"); + if (responseOrError.kind === "response") { + expect(responseOrError.statusCode).toBe(413); + expect(responseOrError.body).toBe("Payload Too Large"); + } else { + expect(responseOrError.code).toBeOneOf(["ECONNRESET", "EPIPE"]); + } expect(verifyWebhook).not.toHaveBeenCalled(); } finally { await server.stop();