Skip to content

Commit 662d1fe

Browse files
committed
fix: bun and node server respect abort signal
Fixes oakserver#651
1 parent bbd2111 commit 662d1fe

File tree

3 files changed

+51
-7
lines changed

3 files changed

+51
-7
lines changed

http_server_bun.test.ts

+26
Original file line numberDiff line numberDiff line change
@@ -125,3 +125,29 @@ Deno.test({
125125
teardown();
126126
},
127127
});
128+
129+
Deno.test({
130+
name: "bun server closes on abort signal",
131+
// this is working but there is some sort of hanging promise somewhere I can't
132+
// narrow down at the moment
133+
ignore: true,
134+
async fn() {
135+
setup([new Request(new URL("http://localhost:8080/"))]);
136+
const controller = new AbortController();
137+
const { signal } = controller;
138+
const server = new Server(createMockApp(), { port: 8080, signal });
139+
const listener = await server.listen();
140+
assertEquals(listener, { addr: { hostname: "localhost", port: 8080 } });
141+
assert(currentServer);
142+
for await (const req of server) {
143+
assert(!req.body);
144+
assertEquals(req.url, "/");
145+
await req.respond(new Response("hello world"));
146+
}
147+
controller.abort();
148+
await currentServer.runPromise;
149+
assertEquals(currentServer.stoppedCount, 1);
150+
assertEquals(currentServer.responses.length, 1);
151+
teardown();
152+
},
153+
});

http_server_bun.ts

+7-3
Original file line numberDiff line numberDiff line change
@@ -166,13 +166,13 @@ class BunRequest implements ServerRequest {
166166
/** An implementation of the oak server abstraction for handling requests on
167167
* Bun using the built in Bun http server. */
168168
export class Server implements OakServer<BunRequest> {
169-
#options: Omit<ServeOptions | ServeTlsOptions, "signal">;
169+
#options: ServeOptions | ServeTlsOptions;
170170
#server?: BunServer;
171171
#stream?: ReadableStream<BunRequest>;
172172

173173
constructor(
174174
_app: Application,
175-
options: Omit<ServeOptions | ServeTlsOptions, "signal">,
175+
options: ServeOptions | ServeTlsOptions,
176176
) {
177177
this.#options = options;
178178
}
@@ -187,7 +187,7 @@ export class Server implements OakServer<BunRequest> {
187187
if (this.#server) {
188188
throw new Error("Server already listening.");
189189
}
190-
const { onListen, hostname, port } = this.#options;
190+
const { onListen, hostname, port, signal } = this.#options;
191191
const tls = isServeTlsOptions(this.#options)
192192
? { key: this.#options.key, cert: this.#options.cert }
193193
: undefined;
@@ -204,6 +204,10 @@ export class Server implements OakServer<BunRequest> {
204204
port,
205205
tls,
206206
});
207+
signal?.addEventListener("abort", () => {
208+
controller.close();
209+
this.close();
210+
}, { once: true });
207211
{
208212
const { hostname, port } = this.#server;
209213
if (onListen) {

http_server_node.ts

+18-4
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,13 @@
66
* @module
77
*/
88

9-
import type { Listener, OakServer, ServerRequest } from "./types.ts";
9+
import type {
10+
Listener,
11+
OakServer,
12+
ServeOptions,
13+
ServerRequest,
14+
ServeTlsOptions,
15+
} from "./types.ts";
1016
import { createPromiseWithResolvers } from "./utils/create_promise_with_resolvers.ts";
1117

1218
// There are quite a few differences between Deno's `std/node/http` and the
@@ -155,10 +161,13 @@ export class Server implements OakServer<NodeRequest> {
155161

156162
constructor(
157163
_app: unknown,
158-
options: Deno.ListenOptions | Deno.ListenTlsOptions,
164+
options: ServeOptions | ServeTlsOptions,
159165
) {
160166
this.#host = options.hostname ?? "127.0.0.1";
161-
this.#port = options.port;
167+
this.#port = options.port ?? 80;
168+
options.signal?.addEventListener("abort", () => {
169+
this.close();
170+
}, { once: true });
162171
}
163172

164173
close(): void {
@@ -169,11 +178,16 @@ export class Server implements OakServer<NodeRequest> {
169178
const { createServer } = await import("node:http");
170179
let server: NodeHttpServer;
171180
this.#requestStream = new ReadableStream({
172-
start(controller) {
181+
start: (controller) => {
173182
server = createServer((req, res) => {
174183
// deno-lint-ignore no-explicit-any
175184
controller.enqueue(new NodeRequest(req as any, res as any));
176185
});
186+
this.#abortController.signal.addEventListener(
187+
"abort",
188+
() => controller.close(),
189+
{ once: true },
190+
);
177191
},
178192
});
179193
server!.listen({

0 commit comments

Comments
 (0)