diff --git a/cli/tests/unit_node/http_test.ts b/cli/tests/unit_node/http_test.ts index 08d2626d74ee1d..e7d743dde3c0db 100644 --- a/cli/tests/unit_node/http_test.ts +++ b/cli/tests/unit_node/http_test.ts @@ -12,6 +12,7 @@ import { deferred } from "../../../test_util/std/async/deferred.ts"; import { gzip } from "node:zlib"; import { Buffer } from "node:buffer"; import { serve } from "../../../test_util/std/http/server.ts"; +import { execCode } from "../unit/test_util.ts"; Deno.test("[node/http listen]", async () => { { @@ -461,3 +462,21 @@ Deno.test("[node/http] ServerResponse _implicitHeader", async () => { await d; }); + +Deno.test("[node/http] server unref", async () => { + const [statusCode, _output] = await execCode(` + import http from "node:http"; + const server = http.createServer((_req, res) => { + res.statusCode = status; + res.end(""); + }); + + // This should let the program to exit without waiting for the + // server to close. + server.unref(); + + server.listen(async () => { + }); + `); + assertEquals(statusCode, 0); +}); diff --git a/ext/node/polyfills/http.ts b/ext/node/polyfills/http.ts index 065ad2e0f5d4ce..101d888f8e3cbf 100644 --- a/ext/node/polyfills/http.ts +++ b/ext/node/polyfills/http.ts @@ -1500,6 +1500,8 @@ class ServerImpl extends EventEmitter { #addr: Deno.NetAddr; #hasClosed = false; + #server: Deno.Server; + #unref = false; #ac?: AbortController; #servePromise: Deferred; listening = false; @@ -1566,7 +1568,7 @@ class ServerImpl extends EventEmitter { return; } this.#ac = ac; - serve( + this.#server = serve( { handler: handler as Deno.ServeHandler, ...this.#addr, @@ -1577,13 +1579,31 @@ class ServerImpl extends EventEmitter { this.emit("listening"); }, }, - ).finished.then(() => this.#servePromise!.resolve()); + ); + if (this.#unref) { + this.#server.unref(); + } + this.#server.finished.then(() => this.#servePromise!.resolve()); } setTimeout() { console.error("Not implemented: Server.setTimeout()"); } + ref() { + if (this.#server) { + this.#server.ref(); + } + this.#unref = false; + } + + unref() { + if (this.#server) { + this.#server.unref(); + } + this.#unref = true; + } + close(cb?: (err?: Error) => void): this { const listening = this.listening; this.listening = false; @@ -1606,6 +1626,7 @@ class ServerImpl extends EventEmitter { this.#servePromise!.resolve(); } + this.#server = undefined; return this; }