mirror of
https://github.com/denoland/deno.git
synced 2025-01-11 08:33:43 -05:00
BREAKING(unstable): change return type of Deno.serve() API (#19189)
This commit changes the return type of an unstable `Deno.serve()` API to instead return a `Deno.Server` object that has a `finished` field. This change is done in preparation to be able to ref/unref the HTTP server.
This commit is contained in:
parent
8724ba9d08
commit
5b07522349
4 changed files with 65 additions and 42 deletions
|
@ -6,7 +6,6 @@ import { TextProtoReader } from "../testdata/run/textproto.ts";
|
|||
import {
|
||||
assert,
|
||||
assertEquals,
|
||||
assertRejects,
|
||||
assertStringIncludes,
|
||||
assertThrows,
|
||||
Deferred,
|
||||
|
@ -50,7 +49,7 @@ Deno.test(async function httpServerShutsDownPortBeforeResolving() {
|
|||
assertThrows(() => Deno.listen({ port: 4501 }));
|
||||
|
||||
ac.abort();
|
||||
await server;
|
||||
await server.finished;
|
||||
|
||||
const listener = Deno.listen({ port: 4501 });
|
||||
listener!.close();
|
||||
|
@ -93,7 +92,7 @@ Deno.test(async function httpServerRejectsOnAddrInUse() {
|
|||
});
|
||||
await listeningPromise;
|
||||
|
||||
await assertRejects(
|
||||
assertThrows(
|
||||
() =>
|
||||
Deno.serve({
|
||||
handler: (_req) => new Response("ok"),
|
||||
|
@ -284,18 +283,18 @@ Deno.test({ permissions: { net: true } }, async function httpServerOverload2() {
|
|||
|
||||
Deno.test(
|
||||
{ permissions: { net: true } },
|
||||
async function httpServerErrorOverloadMissingHandler() {
|
||||
function httpServerErrorOverloadMissingHandler() {
|
||||
// @ts-ignore - testing invalid overload
|
||||
await assertRejects(() => Deno.serve(), TypeError, "handler");
|
||||
assertThrows(() => Deno.serve(), TypeError, "handler");
|
||||
// @ts-ignore - testing invalid overload
|
||||
await assertRejects(() => Deno.serve({}), TypeError, "handler");
|
||||
await assertRejects(
|
||||
assertThrows(() => Deno.serve({}), TypeError, "handler");
|
||||
assertThrows(
|
||||
// @ts-ignore - testing invalid overload
|
||||
() => Deno.serve({ handler: undefined }),
|
||||
TypeError,
|
||||
"handler",
|
||||
);
|
||||
await assertRejects(
|
||||
assertThrows(
|
||||
// @ts-ignore - testing invalid overload
|
||||
() => Deno.serve(undefined, { handler: () => {} }),
|
||||
TypeError,
|
||||
|
|
37
cli/tsc/dts/lib.deno.unstable.d.ts
vendored
37
cli/tsc/dts/lib.deno.unstable.d.ts
vendored
|
@ -1303,6 +1303,16 @@ declare namespace Deno {
|
|||
handler: ServeHandler;
|
||||
}
|
||||
|
||||
/** **UNSTABLE**: New API, yet to be vetted.
|
||||
*
|
||||
* @category HTTP Server
|
||||
*/
|
||||
export interface Server {
|
||||
/** A promise that resolves once server finishes - eg. when aborted using
|
||||
* the signal passed to {@linkcode ServeOptions.signal}.
|
||||
*/
|
||||
finished: Promise<void>;
|
||||
}
|
||||
/** **UNSTABLE**: New API, yet to be vetted.
|
||||
*
|
||||
* Serves HTTP requests with the given handler.
|
||||
|
@ -1331,8 +1341,11 @@ declare namespace Deno {
|
|||
* ```ts
|
||||
* const ac = new AbortController();
|
||||
*
|
||||
* Deno.serve({ signal: ac.signal }, (_req) => new Response("Hello, world"))
|
||||
* .then(() => console.log("Server closed"));
|
||||
* const server = Deno.serve(
|
||||
* { signal: ac.signal },
|
||||
* (_req) => new Response("Hello, world")
|
||||
* );
|
||||
* server.finished.then(() => console.log("Server closed"));
|
||||
*
|
||||
* console.log("Closing server...");
|
||||
* ac.abort();
|
||||
|
@ -1362,7 +1375,7 @@ declare namespace Deno {
|
|||
*
|
||||
* @category HTTP Server
|
||||
*/
|
||||
export function serve(handler: ServeHandler): Promise<void>;
|
||||
export function serve(handler: ServeHandler): Server;
|
||||
/** **UNSTABLE**: New API, yet to be vetted.
|
||||
*
|
||||
* Serves HTTP requests with the given handler.
|
||||
|
@ -1391,8 +1404,11 @@ declare namespace Deno {
|
|||
* ```ts
|
||||
* const ac = new AbortController();
|
||||
*
|
||||
* Deno.serve({ signal: ac.signal }, (_req) => new Response("Hello, world"))
|
||||
* .then(() => console.log("Server closed"));
|
||||
* const server = Deno.serve(
|
||||
* { signal: ac.signal },
|
||||
* (_req) => new Response("Hello, world")
|
||||
* );
|
||||
* server.finished.then(() => console.log("Server closed"));
|
||||
*
|
||||
* console.log("Closing server...");
|
||||
* ac.abort();
|
||||
|
@ -1425,7 +1441,7 @@ declare namespace Deno {
|
|||
export function serve(
|
||||
options: ServeOptions | ServeTlsOptions,
|
||||
handler: ServeHandler,
|
||||
): Promise<void>;
|
||||
): Server;
|
||||
/** **UNSTABLE**: New API, yet to be vetted.
|
||||
*
|
||||
* Serves HTTP requests with the given handler.
|
||||
|
@ -1454,8 +1470,11 @@ declare namespace Deno {
|
|||
* ```ts
|
||||
* const ac = new AbortController();
|
||||
*
|
||||
* Deno.serve({ signal: ac.signal }, (_req) => new Response("Hello, world"))
|
||||
* .then(() => console.log("Server closed"));
|
||||
* const server = Deno.serve(
|
||||
* { signal: ac.signal },
|
||||
* (_req) => new Response("Hello, world")
|
||||
* );
|
||||
* server.finished.then(() => console.log("Server closed"));
|
||||
*
|
||||
* console.log("Closing server...");
|
||||
* ac.abort();
|
||||
|
@ -1487,7 +1506,7 @@ declare namespace Deno {
|
|||
*/
|
||||
export function serve(
|
||||
options: ServeInit & (ServeOptions | ServeTlsOptions),
|
||||
): Promise<void>;
|
||||
): Server;
|
||||
|
||||
/** **UNSTABLE**: New API, yet to be vetted.
|
||||
*
|
||||
|
|
|
@ -563,7 +563,7 @@ function mapToCallback(responseBodies, context, signal, callback, onError) {
|
|||
};
|
||||
}
|
||||
|
||||
async function serve(arg1, arg2) {
|
||||
function serve(arg1, arg2) {
|
||||
let options = undefined;
|
||||
let handler = undefined;
|
||||
if (typeof arg1 === "function") {
|
||||
|
@ -653,33 +653,38 @@ async function serve(arg1, arg2) {
|
|||
|
||||
onListen({ port: listenOpts.port });
|
||||
|
||||
while (true) {
|
||||
const rid = context.serverRid;
|
||||
let req;
|
||||
try {
|
||||
req = await op_http_wait(rid);
|
||||
} catch (error) {
|
||||
if (ObjectPrototypeIsPrototypeOf(BadResourcePrototype, error)) {
|
||||
// Run the server
|
||||
const finished = (async () => {
|
||||
while (true) {
|
||||
const rid = context.serverRid;
|
||||
let req;
|
||||
try {
|
||||
req = await op_http_wait(rid);
|
||||
} catch (error) {
|
||||
if (ObjectPrototypeIsPrototypeOf(BadResourcePrototype, error)) {
|
||||
break;
|
||||
}
|
||||
throw new Deno.errors.Http(error);
|
||||
}
|
||||
if (req === 0xffffffff) {
|
||||
break;
|
||||
}
|
||||
throw new Deno.errors.Http(error);
|
||||
PromisePrototypeCatch(callback(req), (error) => {
|
||||
// Abnormal exit
|
||||
console.error(
|
||||
"Terminating Deno.serve loop due to unexpected error",
|
||||
error,
|
||||
);
|
||||
context.close();
|
||||
});
|
||||
}
|
||||
if (req === 0xffffffff) {
|
||||
break;
|
||||
}
|
||||
PromisePrototypeCatch(callback(req), (error) => {
|
||||
// Abnormal exit
|
||||
console.error(
|
||||
"Terminating Deno.serve loop due to unexpected error",
|
||||
error,
|
||||
);
|
||||
context.close();
|
||||
});
|
||||
}
|
||||
|
||||
for (const streamRid of new SafeSetIterator(responseBodies)) {
|
||||
core.tryClose(streamRid);
|
||||
}
|
||||
for (const streamRid of new SafeSetIterator(responseBodies)) {
|
||||
core.tryClose(streamRid);
|
||||
}
|
||||
})();
|
||||
|
||||
return { finished };
|
||||
}
|
||||
|
||||
internals.upgradeHttpRaw = upgradeHttpRaw;
|
||||
|
|
|
@ -1577,7 +1577,7 @@ class ServerImpl extends EventEmitter {
|
|||
this.emit("listening");
|
||||
},
|
||||
},
|
||||
).then(() => this.#servePromise!.resolve());
|
||||
).finished.then(() => this.#servePromise!.resolve());
|
||||
}
|
||||
|
||||
setTimeout() {
|
||||
|
|
Loading…
Reference in a new issue