mirror of
https://github.com/denoland/deno.git
synced 2025-08-04 10:59:13 +00:00
feat(serve): env var DENO_SERVE_ADDRESS
for configuring default listen address
This commit is contained in:
parent
d07b7ea6f6
commit
dad975b530
5 changed files with 137 additions and 0 deletions
1
Cargo.lock
generated
1
Cargo.lock
generated
|
@ -952,6 +952,7 @@ dependencies = [
|
|||
"serde",
|
||||
"serde_json",
|
||||
"sys_traits",
|
||||
"tempfile",
|
||||
"test_server",
|
||||
"tokio",
|
||||
"url",
|
||||
|
|
|
@ -46,6 +46,11 @@ const {
|
|||
TypedArrayPrototypeGetSymbolToStringTag,
|
||||
Uint8Array,
|
||||
Promise,
|
||||
StringPrototypeSlice,
|
||||
StringPrototypeSplit,
|
||||
StringPrototypeIndexOf,
|
||||
NumberIsSafeInteger,
|
||||
NumberParseInt,
|
||||
} = primordials;
|
||||
|
||||
import { InnerBody } from "ext:deno_fetch/22_body.js";
|
||||
|
@ -767,6 +772,58 @@ function serve(arg1, arg2) {
|
|||
options = { __proto__: null };
|
||||
}
|
||||
|
||||
// const canOverrideOptions = !ObjectHasOwn(options, "path") &&
|
||||
// !ObjectHasOwn(options, "hostname") &&
|
||||
// !ObjectHasOwn(options, "port");
|
||||
const env =
|
||||
Deno.permissions.querySync({ name: "env", variable: "DENO_SERVE_ADDRESS" })
|
||||
.state === "granted" &&
|
||||
Deno.env.get("DENO_SERVE_ADDRESS");
|
||||
|
||||
if (env) {
|
||||
const delim = StringPrototypeIndexOf(env, "/");
|
||||
if (delim >= 0) {
|
||||
const network = StringPrototypeSlice(env, 0, delim);
|
||||
const address = StringPrototypeSlice(env, delim + 1);
|
||||
|
||||
switch (network) {
|
||||
case "tcp": {
|
||||
const ipv6Delim = StringPrototypeIndexOf(address, "]");
|
||||
let hostname: string;
|
||||
let port: number;
|
||||
if (ipv6Delim >= 0) {
|
||||
hostname = StringPrototypeSlice(address, 0, ipv6Delim + 1);
|
||||
port = NumberParseInt(StringPrototypeSlice(address, ipv6Delim + 2));
|
||||
} else {
|
||||
const { 0: hostname_, 1: port_ } = StringPrototypeSplit(
|
||||
address,
|
||||
":",
|
||||
);
|
||||
hostname = hostname_;
|
||||
port = NumberParseInt(port_);
|
||||
}
|
||||
if (!NumberIsSafeInteger(port) || port < 0 || port > 65535) {
|
||||
throw new TypeError(`DENO_SERVE_ADDRESS: Invalid port: ${port}`);
|
||||
}
|
||||
options.hostname = hostname;
|
||||
options.port = port;
|
||||
delete options.path;
|
||||
break;
|
||||
}
|
||||
case "unix": {
|
||||
delete options.hostname;
|
||||
delete options.port;
|
||||
options.path = address;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
// deno-lint-ignore no-console
|
||||
console.error(`DENO_SERVE_ADDRESS: Invalid network type: ${network}`);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const wantsHttps = hasTlsKeyPairOptions(options);
|
||||
const wantsUnix = ObjectHasOwn(options, "path");
|
||||
const signal = options.signal;
|
||||
|
|
|
@ -60,6 +60,7 @@ rustls-tokio-stream.workspace = true
|
|||
serde.workspace = true
|
||||
serde_json.workspace = true
|
||||
sys_traits = { workspace = true, features = ["real", "getrandom", "libc", "winapi"] }
|
||||
tempfile.workspace = true
|
||||
test_util.workspace = true
|
||||
tokio.workspace = true
|
||||
tower-lsp.workspace = true
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
|
||||
use std::cell::RefCell;
|
||||
use std::collections::HashMap;
|
||||
use std::io::BufRead;
|
||||
use std::io::BufReader;
|
||||
use std::io::Read;
|
||||
use std::time::Duration;
|
||||
|
||||
|
@ -267,3 +269,76 @@ async fn deno_serve_parallel() {
|
|||
"bad {serve_counts:?}"
|
||||
);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn deno_run_serve_with_tcp_from_env() {
|
||||
let mut child = util::deno_cmd()
|
||||
.current_dir(util::testdata_path())
|
||||
.arg("run")
|
||||
.arg("--allow-env=DENO_SERVE_ADDRESS")
|
||||
.arg("--allow-net")
|
||||
.arg("./serve/run_serve.ts")
|
||||
.env("DENO_SERVE_ADDRESS", format!("tcp/127.0.0.1:0"))
|
||||
.stdout_piped()
|
||||
.spawn()
|
||||
.unwrap();
|
||||
let stdout = BufReader::new(child.stdout.as_mut().unwrap());
|
||||
let msg = stdout.lines().next().unwrap().unwrap();
|
||||
|
||||
// Deno.serve() listens on 0.0.0.0 by default. This checks DENO_SERVE_ADDRESS
|
||||
// is not ignored by ensuring it's listening on 127.0.0.1.
|
||||
let port_regex = Regex::new(r"http:\/\/127\.0\.0\.1:(\d+)").unwrap();
|
||||
let port = port_regex.captures(&msg).unwrap().get(1).unwrap().as_str();
|
||||
|
||||
let client = reqwest::Client::builder().build().unwrap();
|
||||
|
||||
let res = client
|
||||
.get(&format!("http://127.0.0.1:{port}"))
|
||||
.send()
|
||||
.await
|
||||
.unwrap();
|
||||
assert_eq!(200, res.status());
|
||||
|
||||
let body = res.text().await.unwrap();
|
||||
assert_eq!(body, "Deno.serve() works!");
|
||||
|
||||
child.kill().unwrap();
|
||||
child.wait().unwrap();
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
#[cfg(unix)]
|
||||
async fn deno_run_serve_with_unix_socket_from_env() {
|
||||
use tokio::io::AsyncReadExt;
|
||||
use tokio::io::AsyncWriteExt;
|
||||
use tokio::net::UnixStream;
|
||||
|
||||
let dir = tempfile::TempDir::new().unwrap();
|
||||
let sock = dir.path().join("listen.sock");
|
||||
let mut child = util::deno_cmd()
|
||||
.current_dir(util::testdata_path())
|
||||
.arg("run")
|
||||
.arg("--allow-env=DENO_SERVE_ADDRESS")
|
||||
.arg(format!("--allow-read={}", sock.display()))
|
||||
.arg(format!("--allow-write={}", sock.display()))
|
||||
.arg("./serve/run_serve.ts")
|
||||
.env("DENO_SERVE_ADDRESS", format!("unix/{}", sock.display()))
|
||||
.stdout_piped()
|
||||
.spawn()
|
||||
.unwrap();
|
||||
let stdout = BufReader::new(child.stdout.as_mut().unwrap());
|
||||
stdout.lines().next().unwrap().unwrap();
|
||||
|
||||
// reqwest does not support connecting to unix sockets yet, so here we send the http
|
||||
// payload directly
|
||||
let mut conn = UnixStream::connect(dir.path().join("listen.sock"))
|
||||
.await
|
||||
.unwrap();
|
||||
conn.write_all(b"GET / HTTP/1.0\r\n\r\n").await.unwrap();
|
||||
let mut response = String::new();
|
||||
conn.read_to_string(&mut response).await.unwrap();
|
||||
assert!(response.ends_with("\r\nDeno.serve() works!"));
|
||||
|
||||
child.kill().unwrap();
|
||||
child.wait().unwrap();
|
||||
}
|
||||
|
|
3
tests/testdata/serve/run_serve.ts
vendored
Normal file
3
tests/testdata/serve/run_serve.ts
vendored
Normal file
|
@ -0,0 +1,3 @@
|
|||
Deno.serve((_req: Request) => {
|
||||
return new Response("Deno.serve() works!");
|
||||
});
|
Loading…
Add table
Add a link
Reference in a new issue