mirror of
https://github.com/denoland/deno.git
synced 2024-11-28 16:20:57 -05:00
feat: stabilize Deno.HttpServer.shutdown and Unix socket support (#21463)
This commit stabilizes "Deno.HttpServer.shutdown" API as well as Unix socket support in "Deno.serve" API. --------- Co-authored-by: Yoshiya Hinosawa <stibium121@gmail.com>
This commit is contained in:
parent
e372fc73e8
commit
a931a47511
3 changed files with 130 additions and 142 deletions
125
cli/tsc/dts/lib.deno.ns.d.ts
vendored
125
cli/tsc/dts/lib.deno.ns.d.ts
vendored
|
@ -5939,6 +5939,50 @@ declare namespace Deno {
|
||||||
handler: ServeHandler;
|
handler: ServeHandler;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface ServeUnixOptions {
|
||||||
|
/** The unix domain socket path to listen on. */
|
||||||
|
path: string;
|
||||||
|
|
||||||
|
/** An {@linkcode AbortSignal} to close the server and all connections. */
|
||||||
|
signal?: AbortSignal;
|
||||||
|
|
||||||
|
/** The handler to invoke when route handlers throw an error. */
|
||||||
|
onError?: (error: unknown) => Response | Promise<Response>;
|
||||||
|
|
||||||
|
/** The callback which is called when the server starts listening. */
|
||||||
|
onListen?: (params: { path: string }) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Information for a unix domain socket HTTP request.
|
||||||
|
*
|
||||||
|
* @category HTTP Server
|
||||||
|
*/
|
||||||
|
export interface ServeUnixHandlerInfo {
|
||||||
|
/** The remote address of the connection. */
|
||||||
|
remoteAddr: Deno.UnixAddr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** A handler for unix domain socket HTTP requests. Consumes a request and returns a response.
|
||||||
|
*
|
||||||
|
* If a handler throws, the server calling the handler will assume the impact
|
||||||
|
* of the error is isolated to the individual request. It will catch the error
|
||||||
|
* and if necessary will close the underlying connection.
|
||||||
|
*
|
||||||
|
* @category HTTP Server
|
||||||
|
*/
|
||||||
|
export type ServeUnixHandler = (
|
||||||
|
request: Request,
|
||||||
|
info: ServeUnixHandlerInfo,
|
||||||
|
) => Response | Promise<Response>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @category HTTP Server
|
||||||
|
*/
|
||||||
|
export interface ServeUnixInit {
|
||||||
|
/** The handler to invoke to process each incoming request. */
|
||||||
|
handler: ServeUnixHandler;
|
||||||
|
}
|
||||||
|
|
||||||
/** An instance of the server created using `Deno.serve()` API.
|
/** An instance of the server created using `Deno.serve()` API.
|
||||||
*
|
*
|
||||||
* @category HTTP Server
|
* @category HTTP Server
|
||||||
|
@ -5959,6 +6003,11 @@ declare namespace Deno {
|
||||||
|
|
||||||
/** Make the server not block the event loop from finishing. */
|
/** Make the server not block the event loop from finishing. */
|
||||||
unref(): void;
|
unref(): void;
|
||||||
|
|
||||||
|
/** Gracefully close the server. No more new connections will be accepted,
|
||||||
|
* while pending requests will be allowed to finish.
|
||||||
|
*/
|
||||||
|
shutdown(): Promise<void>;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -5978,6 +6027,55 @@ declare namespace Deno {
|
||||||
* @category HTTP Server
|
* @category HTTP Server
|
||||||
*/
|
*/
|
||||||
export function serve(handler: ServeHandler): HttpServer;
|
export function serve(handler: ServeHandler): HttpServer;
|
||||||
|
/** Serves HTTP requests with the given option bag and handler.
|
||||||
|
*
|
||||||
|
* You can specify the socket path with `path` option.
|
||||||
|
*
|
||||||
|
* ```ts
|
||||||
|
* Deno.serve(
|
||||||
|
* { path: "path/to/socket" },
|
||||||
|
* (_req) => new Response("Hello, world")
|
||||||
|
* );
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* You can stop the server with an {@linkcode AbortSignal}. The abort signal
|
||||||
|
* needs to be passed as the `signal` option in the options bag. The server
|
||||||
|
* aborts when the abort signal is aborted. To wait for the server to close,
|
||||||
|
* await the promise returned from the `Deno.serve` API.
|
||||||
|
*
|
||||||
|
* ```ts
|
||||||
|
* const ac = new AbortController();
|
||||||
|
*
|
||||||
|
* const server = Deno.serve(
|
||||||
|
* { signal: ac.signal, path: "path/to/socket" },
|
||||||
|
* (_req) => new Response("Hello, world")
|
||||||
|
* );
|
||||||
|
* server.finished.then(() => console.log("Server closed"));
|
||||||
|
*
|
||||||
|
* console.log("Closing server...");
|
||||||
|
* ac.abort();
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* By default `Deno.serve` prints the message
|
||||||
|
* `Listening on path/to/socket` on listening. If you like to
|
||||||
|
* change this behavior, you can specify a custom `onListen` callback.
|
||||||
|
*
|
||||||
|
* ```ts
|
||||||
|
* Deno.serve({
|
||||||
|
* onListen({ path }) {
|
||||||
|
* console.log(`Server started at ${path}`);
|
||||||
|
* // ... more info specific to your server ..
|
||||||
|
* },
|
||||||
|
* path: "path/to/socket",
|
||||||
|
* }, (_req) => new Response("Hello, world"));
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* @category HTTP Server
|
||||||
|
*/
|
||||||
|
export function serve(
|
||||||
|
options: ServeUnixOptions,
|
||||||
|
handler: ServeUnixHandler,
|
||||||
|
): HttpServer;
|
||||||
/** Serves HTTP requests with the given option bag and handler.
|
/** Serves HTTP requests with the given option bag and handler.
|
||||||
*
|
*
|
||||||
* You can specify an object with a port and hostname option, which is the
|
* You can specify an object with a port and hostname option, which is the
|
||||||
|
@ -6038,6 +6136,33 @@ declare namespace Deno {
|
||||||
options: ServeOptions | ServeTlsOptions,
|
options: ServeOptions | ServeTlsOptions,
|
||||||
handler: ServeHandler,
|
handler: ServeHandler,
|
||||||
): HttpServer;
|
): HttpServer;
|
||||||
|
/** Serves HTTP requests with the given option bag.
|
||||||
|
*
|
||||||
|
* You can specify an object with the path option, which is the
|
||||||
|
* unix domain socket to listen on.
|
||||||
|
*
|
||||||
|
* ```ts
|
||||||
|
* const ac = new AbortController();
|
||||||
|
*
|
||||||
|
* const server = Deno.serve({
|
||||||
|
* path: "path/to/socket",
|
||||||
|
* handler: (_req) => new Response("Hello, world"),
|
||||||
|
* signal: ac.signal,
|
||||||
|
* onListen({ path }) {
|
||||||
|
* console.log(`Server started at ${path}`);
|
||||||
|
* },
|
||||||
|
* });
|
||||||
|
* server.finished.then(() => console.log("Server closed"));
|
||||||
|
*
|
||||||
|
* console.log("Closing server...");
|
||||||
|
* ac.abort();
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* @category HTTP Server
|
||||||
|
*/
|
||||||
|
export function serve(
|
||||||
|
options: ServeUnixInit & ServeUnixOptions,
|
||||||
|
): HttpServer;
|
||||||
/** Serves HTTP requests with the given option bag.
|
/** Serves HTTP requests with the given option bag.
|
||||||
*
|
*
|
||||||
* You can specify an object with a port and hostname option, which is the
|
* You can specify an object with a port and hostname option, which is the
|
||||||
|
|
132
cli/tsc/dts/lib.deno.unstable.d.ts
vendored
132
cli/tsc/dts/lib.deno.unstable.d.ts
vendored
|
@ -2099,138 +2099,6 @@ declare namespace Deno {
|
||||||
readonly value: bigint;
|
readonly value: bigint;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** An instance of the server created using `Deno.serve()` API.
|
|
||||||
*
|
|
||||||
* @category HTTP Server
|
|
||||||
*/
|
|
||||||
export interface HttpServer {
|
|
||||||
/** Gracefully close the server. No more new connections will be accepted,
|
|
||||||
* while pending requests will be allowed to finish.
|
|
||||||
*/
|
|
||||||
shutdown(): Promise<void>;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface ServeUnixOptions {
|
|
||||||
/** The unix domain socket path to listen on. */
|
|
||||||
path: string;
|
|
||||||
|
|
||||||
/** An {@linkcode AbortSignal} to close the server and all connections. */
|
|
||||||
signal?: AbortSignal;
|
|
||||||
|
|
||||||
/** The handler to invoke when route handlers throw an error. */
|
|
||||||
onError?: (error: unknown) => Response | Promise<Response>;
|
|
||||||
|
|
||||||
/** The callback which is called when the server starts listening. */
|
|
||||||
onListen?: (params: { path: string }) => void;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Information for a unix domain socket HTTP request.
|
|
||||||
*
|
|
||||||
* @category HTTP Server
|
|
||||||
*/
|
|
||||||
export interface ServeUnixHandlerInfo {
|
|
||||||
/** The remote address of the connection. */
|
|
||||||
remoteAddr: Deno.UnixAddr;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** A handler for unix domain socket HTTP requests. Consumes a request and returns a response.
|
|
||||||
*
|
|
||||||
* If a handler throws, the server calling the handler will assume the impact
|
|
||||||
* of the error is isolated to the individual request. It will catch the error
|
|
||||||
* and if necessary will close the underlying connection.
|
|
||||||
*
|
|
||||||
* @category HTTP Server
|
|
||||||
*/
|
|
||||||
export type ServeUnixHandler = (
|
|
||||||
request: Request,
|
|
||||||
info: ServeUnixHandlerInfo,
|
|
||||||
) => Response | Promise<Response>;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @category HTTP Server
|
|
||||||
*/
|
|
||||||
export interface ServeUnixInit {
|
|
||||||
/** The handler to invoke to process each incoming request. */
|
|
||||||
handler: ServeUnixHandler;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Serves HTTP requests with the given option bag and handler.
|
|
||||||
*
|
|
||||||
* You can specify the socket path with `path` option.
|
|
||||||
*
|
|
||||||
* ```ts
|
|
||||||
* Deno.serve(
|
|
||||||
* { path: "path/to/socket" },
|
|
||||||
* (_req) => new Response("Hello, world")
|
|
||||||
* );
|
|
||||||
* ```
|
|
||||||
*
|
|
||||||
* You can stop the server with an {@linkcode AbortSignal}. The abort signal
|
|
||||||
* needs to be passed as the `signal` option in the options bag. The server
|
|
||||||
* aborts when the abort signal is aborted. To wait for the server to close,
|
|
||||||
* await the promise returned from the `Deno.serve` API.
|
|
||||||
*
|
|
||||||
* ```ts
|
|
||||||
* const ac = new AbortController();
|
|
||||||
*
|
|
||||||
* const server = Deno.serve(
|
|
||||||
* { signal: ac.signal, path: "path/to/socket" },
|
|
||||||
* (_req) => new Response("Hello, world")
|
|
||||||
* );
|
|
||||||
* server.finished.then(() => console.log("Server closed"));
|
|
||||||
*
|
|
||||||
* console.log("Closing server...");
|
|
||||||
* ac.abort();
|
|
||||||
* ```
|
|
||||||
*
|
|
||||||
* By default `Deno.serve` prints the message
|
|
||||||
* `Listening on path/to/socket` on listening. If you like to
|
|
||||||
* change this behavior, you can specify a custom `onListen` callback.
|
|
||||||
*
|
|
||||||
* ```ts
|
|
||||||
* Deno.serve({
|
|
||||||
* onListen({ path }) {
|
|
||||||
* console.log(`Server started at ${path}`);
|
|
||||||
* // ... more info specific to your server ..
|
|
||||||
* },
|
|
||||||
* path: "path/to/socket",
|
|
||||||
* }, (_req) => new Response("Hello, world"));
|
|
||||||
* ```
|
|
||||||
*
|
|
||||||
* @category HTTP Server
|
|
||||||
*/
|
|
||||||
export function serve(
|
|
||||||
options: ServeUnixOptions,
|
|
||||||
handler: ServeUnixHandler,
|
|
||||||
): Server;
|
|
||||||
/** Serves HTTP requests with the given option bag.
|
|
||||||
*
|
|
||||||
* You can specify an object with the path option, which is the
|
|
||||||
* unix domain socket to listen on.
|
|
||||||
*
|
|
||||||
* ```ts
|
|
||||||
* const ac = new AbortController();
|
|
||||||
*
|
|
||||||
* const server = Deno.serve({
|
|
||||||
* path: "path/to/socket",
|
|
||||||
* handler: (_req) => new Response("Hello, world"),
|
|
||||||
* signal: ac.signal,
|
|
||||||
* onListen({ path }) {
|
|
||||||
* console.log(`Server started at ${path}`);
|
|
||||||
* },
|
|
||||||
* });
|
|
||||||
* server.finished.then(() => console.log("Server closed"));
|
|
||||||
*
|
|
||||||
* console.log("Closing server...");
|
|
||||||
* ac.abort();
|
|
||||||
* ```
|
|
||||||
*
|
|
||||||
* @category HTTP Server
|
|
||||||
*/
|
|
||||||
export function serve(
|
|
||||||
options: ServeUnixInit & ServeUnixOptions,
|
|
||||||
): Server;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A namespace containing runtime APIs available in Jupyter notebooks.
|
* A namespace containing runtime APIs available in Jupyter notebooks.
|
||||||
*
|
*
|
||||||
|
|
|
@ -87,6 +87,11 @@ static USE_WRITEV: Lazy<bool> = Lazy::new(|| {
|
||||||
false
|
false
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// NOTE(bartlomieju): currently we don't have any unstable HTTP features,
|
||||||
|
// but let's keep this const here, because:
|
||||||
|
// a) we still need to support `--unstable-http` flag to not break user's CLI;
|
||||||
|
// b) we might add more unstable features in the future.
|
||||||
|
#[allow(dead_code)]
|
||||||
pub const UNSTABLE_FEATURE_NAME: &str = "http";
|
pub const UNSTABLE_FEATURE_NAME: &str = "http";
|
||||||
|
|
||||||
/// All HTTP/2 connections start with this byte string.
|
/// All HTTP/2 connections start with this byte string.
|
||||||
|
@ -1183,16 +1188,6 @@ pub async fn op_http_close(
|
||||||
|
|
||||||
if graceful {
|
if graceful {
|
||||||
http_general_trace!("graceful shutdown");
|
http_general_trace!("graceful shutdown");
|
||||||
// TODO(bartlomieju): replace with `state.feature_checker.check_or_exit`
|
|
||||||
// once we phase out `check_or_exit_with_legacy_fallback`
|
|
||||||
state
|
|
||||||
.borrow()
|
|
||||||
.feature_checker
|
|
||||||
.check_or_exit_with_legacy_fallback(
|
|
||||||
UNSTABLE_FEATURE_NAME,
|
|
||||||
"Deno.Server.shutdown",
|
|
||||||
);
|
|
||||||
|
|
||||||
// In a graceful shutdown, we close the listener and allow all the remaining connections to drain
|
// In a graceful shutdown, we close the listener and allow all the remaining connections to drain
|
||||||
join_handle.listen_cancel_handle().cancel();
|
join_handle.listen_cancel_handle().cancel();
|
||||||
poll_fn(|cx| join_handle.server_state.poll_complete(cx)).await;
|
poll_fn(|cx| join_handle.server_state.poll_complete(cx)).await;
|
||||||
|
|
Loading…
Reference in a new issue