summaryrefslogtreecommitdiff
path: root/ext
diff options
context:
space:
mode:
authorYoshiya Hinosawa <stibium121@gmail.com>2023-10-04 11:37:39 +0900
committerGitHub <noreply@github.com>2023-10-04 11:37:39 +0900
commitda0b945804f19903beac71b23ff1040ebdb9b554 (patch)
tree8ec0508fbc04839f113b2d58169090d14b474cdd /ext
parent8c1677ecbcbb474fc6a5ac9b5f73b562677bb829 (diff)
feat(unstable): add unix domain socket support to Deno.serve (#20759)
Diffstat (limited to 'ext')
-rw-r--r--ext/http/00_serve.js44
-rw-r--r--ext/net/01_net.js9
-rw-r--r--ext/net/ops_unix.rs8
3 files changed, 53 insertions, 8 deletions
diff --git a/ext/http/00_serve.js b/ext/http/00_serve.js
index aeebca93d..e74e1e71f 100644
--- a/ext/http/00_serve.js
+++ b/ext/http/00_serve.js
@@ -34,11 +34,12 @@ import {
ReadableStreamPrototype,
resourceForReadableStream,
} from "ext:deno_web/06_streams.js";
-import { listen, TcpConn } from "ext:deno_net/01_net.js";
+import { listen, listenOptionApiName, TcpConn } from "ext:deno_net/01_net.js";
import { listenTls } from "ext:deno_net/02_tls.js";
const {
ArrayPrototypePush,
Error,
+ ObjectHasOwn,
ObjectPrototypeIsPrototypeOf,
PromisePrototypeCatch,
Symbol,
@@ -272,6 +273,13 @@ class InnerRequest {
}
get remoteAddr() {
+ const transport = this.#context.listener?.addr.transport;
+ if (transport === "unix" || transport === "unixpacket") {
+ return {
+ transport,
+ path: this.#context.listener.addr.path,
+ };
+ }
if (this.#methodAndUri === undefined) {
if (this.#slabId === undefined) {
throw new TypeError("request closed");
@@ -337,8 +345,9 @@ class CallbackContext {
serverRid;
closed;
closing;
+ listener;
- constructor(signal, args) {
+ constructor(signal, args, listener) {
// The abort signal triggers a non-graceful shutdown
signal?.addEventListener(
"abort",
@@ -352,6 +361,7 @@ class CallbackContext {
this.scheme = args[1];
this.fallbackHost = args[2];
this.closed = false;
+ this.listener = listener;
}
close() {
@@ -519,11 +529,29 @@ function serve(arg1, arg2) {
}
const wantsHttps = options.cert || options.key;
+ const wantsUnix = ObjectHasOwn(options, "path");
const signal = options.signal;
const onError = options.onError ?? function (error) {
console.error(error);
return internalServerError();
};
+
+ if (wantsUnix) {
+ const listener = listen({
+ transport: "unix",
+ path: options.path,
+ [listenOptionApiName]: "Deno.serve",
+ });
+ const path = listener.addr.path;
+ return serveHttpOnListener(listener, signal, handler, onError, () => {
+ if (options.onListen) {
+ options.onListen({ path });
+ } else {
+ console.log(`Listening on ${path}`);
+ }
+ });
+ }
+
const listenOpts = {
hostname: options.hostname ?? "0.0.0.0",
port: options.port ?? 8000,
@@ -581,7 +609,11 @@ function serve(arg1, arg2) {
* Serve HTTP/1.1 and/or HTTP/2 on an arbitrary listener.
*/
function serveHttpOnListener(listener, signal, handler, onError, onListen) {
- const context = new CallbackContext(signal, op_http_serve(listener.rid));
+ const context = new CallbackContext(
+ signal,
+ op_http_serve(listener.rid),
+ listener,
+ );
const callback = mapToCallback(context, handler, onError);
onListen(context.scheme);
@@ -593,7 +625,11 @@ function serveHttpOnListener(listener, signal, handler, onError, onListen) {
* Serve HTTP/1.1 and/or HTTP/2 on an arbitrary connection.
*/
function serveHttpOnConnection(connection, signal, handler, onError, onListen) {
- const context = new CallbackContext(signal, op_http_serve_on(connection.rid));
+ const context = new CallbackContext(
+ signal,
+ op_http_serve_on(connection.rid),
+ null,
+ );
const callback = mapToCallback(context, handler, onError);
onListen(context.scheme);
diff --git a/ext/net/01_net.js b/ext/net/01_net.js
index 9cdcdb78c..f2bf5e7df 100644
--- a/ext/net/01_net.js
+++ b/ext/net/01_net.js
@@ -19,6 +19,7 @@ const {
ObjectPrototypeIsPrototypeOf,
PromiseResolve,
SymbolAsyncIterator,
+ Symbol,
SymbolFor,
TypeError,
TypedArrayPrototypeSubarray,
@@ -416,6 +417,8 @@ class Datagram {
}
}
+const listenOptionApiName = Symbol("listenOptionApiName");
+
function listen(args) {
switch (args.transport ?? "tcp") {
case "tcp": {
@@ -427,7 +430,10 @@ function listen(args) {
return new Listener(rid, addr);
}
case "unix": {
- const { 0: rid, 1: path } = ops.op_net_listen_unix(args.path);
+ const { 0: rid, 1: path } = ops.op_net_listen_unix(
+ args.path,
+ args[listenOptionApiName] ?? "Deno.listen",
+ );
const addr = {
transport: "unix",
path,
@@ -505,6 +511,7 @@ export {
Datagram,
listen,
Listener,
+ listenOptionApiName,
resolveDns,
shutdown,
TcpConn,
diff --git a/ext/net/ops_unix.rs b/ext/net/ops_unix.rs
index beb41bb4a..7a5da9fa1 100644
--- a/ext/net/ops_unix.rs
+++ b/ext/net/ops_unix.rs
@@ -194,15 +194,17 @@ where
pub fn op_net_listen_unix<NP>(
state: &mut OpState,
#[string] path: String,
+ #[string] api_name: String,
) -> Result<(ResourceId, Option<String>), AnyError>
where
NP: NetPermissions + 'static,
{
let address_path = Path::new(&path);
- super::check_unstable(state, "Deno.listen");
+ super::check_unstable(state, &api_name);
let permissions = state.borrow_mut::<NP>();
- permissions.check_read(address_path, "Deno.listen()")?;
- permissions.check_write(address_path, "Deno.listen()")?;
+ let api_call_expr = format!("{}()", api_name);
+ permissions.check_read(address_path, &api_call_expr)?;
+ permissions.check_write(address_path, &api_call_expr)?;
let listener = UnixListener::bind(address_path)?;
let local_addr = listener.local_addr()?;
let pathname = local_addr.as_pathname().map(pathstring).transpose()?;