Skip to content

Commit 4ea595c

Browse files
authored
fix(gateway): skip ending destroyed plugin responses
1 parent fb2cd29 commit 4ea595c

2 files changed

Lines changed: 28 additions & 1 deletion

File tree

src/gateway/server/plugins-http.test.ts

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -519,6 +519,33 @@ describe("createGatewayPluginRequestHandler", () => {
519519
});
520520
}
521521
});
522+
523+
it("does not end a response the plugin already destroyed before throwing", async () => {
524+
const log = createPluginLog();
525+
const handler = createGatewayPluginRequestHandler({
526+
registry: createTestRegistry({
527+
httpRoutes: [
528+
createRoute({
529+
path: "/destroyed",
530+
handler: async (_req, res) => {
531+
Object.defineProperty(res, "headersSent", { value: true, configurable: true });
532+
res.destroy();
533+
throw new Error("boom");
534+
},
535+
}),
536+
],
537+
}),
538+
log,
539+
});
540+
const { res, end } = makeMockHttpResponse();
541+
542+
const handled = await handler({ url: "/destroyed" } as IncomingMessage, res);
543+
544+
expect(handled).toBe(true);
545+
expect(res.destroyed).toBe(true);
546+
expect(end).not.toHaveBeenCalled();
547+
expect(log.warn).toHaveBeenCalledWith("plugin http route failed (route): Error: boom");
548+
});
522549
});
523550

524551
describe("createGatewayPluginUpgradeHandler", () => {

src/gateway/server/plugins-http.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -201,7 +201,7 @@ export function createGatewayPluginRequestHandler(params: {
201201
res.statusCode = 500;
202202
res.setHeader("Content-Type", "text/plain; charset=utf-8");
203203
res.end("Internal Server Error");
204-
} else if (!res.writableEnded) {
204+
} else if (!res.writableEnded && !res.destroyed) {
205205
res.end();
206206
}
207207
return true;

0 commit comments

Comments
 (0)