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 {
|
import {
|
||||||
assert,
|
assert,
|
||||||
assertEquals,
|
assertEquals,
|
||||||
assertRejects,
|
|
||||||
assertStringIncludes,
|
assertStringIncludes,
|
||||||
assertThrows,
|
assertThrows,
|
||||||
Deferred,
|
Deferred,
|
||||||
|
@ -50,7 +49,7 @@ Deno.test(async function httpServerShutsDownPortBeforeResolving() {
|
||||||
assertThrows(() => Deno.listen({ port: 4501 }));
|
assertThrows(() => Deno.listen({ port: 4501 }));
|
||||||
|
|
||||||
ac.abort();
|
ac.abort();
|
||||||
await server;
|
await server.finished;
|
||||||
|
|
||||||
const listener = Deno.listen({ port: 4501 });
|
const listener = Deno.listen({ port: 4501 });
|
||||||
listener!.close();
|
listener!.close();
|
||||||
|
@ -93,7 +92,7 @@ Deno.test(async function httpServerRejectsOnAddrInUse() {
|
||||||
});
|
});
|
||||||
await listeningPromise;
|
await listeningPromise;
|
||||||
|
|
||||||
await assertRejects(
|
assertThrows(
|
||||||
() =>
|
() =>
|
||||||
Deno.serve({
|
Deno.serve({
|
||||||
handler: (_req) => new Response("ok"),
|
handler: (_req) => new Response("ok"),
|
||||||
|
@ -284,18 +283,18 @@ Deno.test({ permissions: { net: true } }, async function httpServerOverload2() {
|
||||||
|
|
||||||
Deno.test(
|
Deno.test(
|
||||||
{ permissions: { net: true } },
|
{ permissions: { net: true } },
|
||||||
async function httpServerErrorOverloadMissingHandler() {
|
function httpServerErrorOverloadMissingHandler() {
|
||||||
// @ts-ignore - testing invalid overload
|
// @ts-ignore - testing invalid overload
|
||||||
await assertRejects(() => Deno.serve(), TypeError, "handler");
|
assertThrows(() => Deno.serve(), TypeError, "handler");
|
||||||
// @ts-ignore - testing invalid overload
|
// @ts-ignore - testing invalid overload
|
||||||
await assertRejects(() => Deno.serve({}), TypeError, "handler");
|
assertThrows(() => Deno.serve({}), TypeError, "handler");
|
||||||
await assertRejects(
|
assertThrows(
|
||||||
// @ts-ignore - testing invalid overload
|
// @ts-ignore - testing invalid overload
|
||||||
() => Deno.serve({ handler: undefined }),
|
() => Deno.serve({ handler: undefined }),
|
||||||
TypeError,
|
TypeError,
|
||||||
"handler",
|
"handler",
|
||||||
);
|
);
|
||||||
await assertRejects(
|
assertThrows(
|
||||||
// @ts-ignore - testing invalid overload
|
// @ts-ignore - testing invalid overload
|
||||||
() => Deno.serve(undefined, { handler: () => {} }),
|
() => Deno.serve(undefined, { handler: () => {} }),
|
||||||
TypeError,
|
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;
|
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.
|
/** **UNSTABLE**: New API, yet to be vetted.
|
||||||
*
|
*
|
||||||
* Serves HTTP requests with the given handler.
|
* Serves HTTP requests with the given handler.
|
||||||
|
@ -1331,8 +1341,11 @@ declare namespace Deno {
|
||||||
* ```ts
|
* ```ts
|
||||||
* const ac = new AbortController();
|
* const ac = new AbortController();
|
||||||
*
|
*
|
||||||
* Deno.serve({ signal: ac.signal }, (_req) => new Response("Hello, world"))
|
* const server = Deno.serve(
|
||||||
* .then(() => console.log("Server closed"));
|
* { signal: ac.signal },
|
||||||
|
* (_req) => new Response("Hello, world")
|
||||||
|
* );
|
||||||
|
* server.finished.then(() => console.log("Server closed"));
|
||||||
*
|
*
|
||||||
* console.log("Closing server...");
|
* console.log("Closing server...");
|
||||||
* ac.abort();
|
* ac.abort();
|
||||||
|
@ -1362,7 +1375,7 @@ declare namespace Deno {
|
||||||
*
|
*
|
||||||
* @category HTTP Server
|
* @category HTTP Server
|
||||||
*/
|
*/
|
||||||
export function serve(handler: ServeHandler): Promise<void>;
|
export function serve(handler: ServeHandler): Server;
|
||||||
/** **UNSTABLE**: New API, yet to be vetted.
|
/** **UNSTABLE**: New API, yet to be vetted.
|
||||||
*
|
*
|
||||||
* Serves HTTP requests with the given handler.
|
* Serves HTTP requests with the given handler.
|
||||||
|
@ -1391,8 +1404,11 @@ declare namespace Deno {
|
||||||
* ```ts
|
* ```ts
|
||||||
* const ac = new AbortController();
|
* const ac = new AbortController();
|
||||||
*
|
*
|
||||||
* Deno.serve({ signal: ac.signal }, (_req) => new Response("Hello, world"))
|
* const server = Deno.serve(
|
||||||
* .then(() => console.log("Server closed"));
|
* { signal: ac.signal },
|
||||||
|
* (_req) => new Response("Hello, world")
|
||||||
|
* );
|
||||||
|
* server.finished.then(() => console.log("Server closed"));
|
||||||
*
|
*
|
||||||
* console.log("Closing server...");
|
* console.log("Closing server...");
|
||||||
* ac.abort();
|
* ac.abort();
|
||||||
|
@ -1425,7 +1441,7 @@ declare namespace Deno {
|
||||||
export function serve(
|
export function serve(
|
||||||
options: ServeOptions | ServeTlsOptions,
|
options: ServeOptions | ServeTlsOptions,
|
||||||
handler: ServeHandler,
|
handler: ServeHandler,
|
||||||
): Promise<void>;
|
): Server;
|
||||||
/** **UNSTABLE**: New API, yet to be vetted.
|
/** **UNSTABLE**: New API, yet to be vetted.
|
||||||
*
|
*
|
||||||
* Serves HTTP requests with the given handler.
|
* Serves HTTP requests with the given handler.
|
||||||
|
@ -1454,8 +1470,11 @@ declare namespace Deno {
|
||||||
* ```ts
|
* ```ts
|
||||||
* const ac = new AbortController();
|
* const ac = new AbortController();
|
||||||
*
|
*
|
||||||
* Deno.serve({ signal: ac.signal }, (_req) => new Response("Hello, world"))
|
* const server = Deno.serve(
|
||||||
* .then(() => console.log("Server closed"));
|
* { signal: ac.signal },
|
||||||
|
* (_req) => new Response("Hello, world")
|
||||||
|
* );
|
||||||
|
* server.finished.then(() => console.log("Server closed"));
|
||||||
*
|
*
|
||||||
* console.log("Closing server...");
|
* console.log("Closing server...");
|
||||||
* ac.abort();
|
* ac.abort();
|
||||||
|
@ -1487,7 +1506,7 @@ declare namespace Deno {
|
||||||
*/
|
*/
|
||||||
export function serve(
|
export function serve(
|
||||||
options: ServeInit & (ServeOptions | ServeTlsOptions),
|
options: ServeInit & (ServeOptions | ServeTlsOptions),
|
||||||
): Promise<void>;
|
): Server;
|
||||||
|
|
||||||
/** **UNSTABLE**: New API, yet to be vetted.
|
/** **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 options = undefined;
|
||||||
let handler = undefined;
|
let handler = undefined;
|
||||||
if (typeof arg1 === "function") {
|
if (typeof arg1 === "function") {
|
||||||
|
@ -653,33 +653,38 @@ async function serve(arg1, arg2) {
|
||||||
|
|
||||||
onListen({ port: listenOpts.port });
|
onListen({ port: listenOpts.port });
|
||||||
|
|
||||||
while (true) {
|
// Run the server
|
||||||
const rid = context.serverRid;
|
const finished = (async () => {
|
||||||
let req;
|
while (true) {
|
||||||
try {
|
const rid = context.serverRid;
|
||||||
req = await op_http_wait(rid);
|
let req;
|
||||||
} catch (error) {
|
try {
|
||||||
if (ObjectPrototypeIsPrototypeOf(BadResourcePrototype, error)) {
|
req = await op_http_wait(rid);
|
||||||
|
} catch (error) {
|
||||||
|
if (ObjectPrototypeIsPrototypeOf(BadResourcePrototype, error)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
throw new Deno.errors.Http(error);
|
||||||
|
}
|
||||||
|
if (req === 0xffffffff) {
|
||||||
break;
|
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)) {
|
for (const streamRid of new SafeSetIterator(responseBodies)) {
|
||||||
core.tryClose(streamRid);
|
core.tryClose(streamRid);
|
||||||
}
|
}
|
||||||
|
})();
|
||||||
|
|
||||||
|
return { finished };
|
||||||
}
|
}
|
||||||
|
|
||||||
internals.upgradeHttpRaw = upgradeHttpRaw;
|
internals.upgradeHttpRaw = upgradeHttpRaw;
|
||||||
|
|
|
@ -1577,7 +1577,7 @@ class ServerImpl extends EventEmitter {
|
||||||
this.emit("listening");
|
this.emit("listening");
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
).then(() => this.#servePromise!.resolve());
|
).finished.then(() => this.#servePromise!.resolve());
|
||||||
}
|
}
|
||||||
|
|
||||||
setTimeout() {
|
setTimeout() {
|
||||||
|
|
Loading…
Reference in a new issue