mirror of
https://github.com/denoland/deno.git
synced 2024-11-24 15:19:26 -05:00
feat(serve): env var DENO_SERVE_ADDRESS
for configuring default listen address
This commit is contained in:
parent
f4b9d85862
commit
82c97d3fd4
6 changed files with 124 additions and 0 deletions
1
Cargo.lock
generated
1
Cargo.lock
generated
|
@ -744,6 +744,7 @@ dependencies = [
|
||||||
"pretty_assertions",
|
"pretty_assertions",
|
||||||
"regex",
|
"regex",
|
||||||
"serde",
|
"serde",
|
||||||
|
"tempfile",
|
||||||
"test_server",
|
"test_server",
|
||||||
"tokio",
|
"tokio",
|
||||||
"tower-lsp",
|
"tower-lsp",
|
||||||
|
|
|
@ -1100,6 +1100,8 @@ static ENV_VARIABLES_HELP: &str = color_print::cstr!(
|
||||||
<g>DENO_NO_UPDATE_CHECK</> Set to disable checking if a newer Deno version is
|
<g>DENO_NO_UPDATE_CHECK</> Set to disable checking if a newer Deno version is
|
||||||
available
|
available
|
||||||
|
|
||||||
|
<g>DENO_SERVE_ADDRESS</> Default listening address for `Deno.serve()`
|
||||||
|
|
||||||
<g>DENO_TLS_CA_STORE</> Comma-separated list of order dependent certificate
|
<g>DENO_TLS_CA_STORE</> Comma-separated list of order dependent certificate
|
||||||
stores. Possible values: "system", "mozilla".
|
stores. Possible values: "system", "mozilla".
|
||||||
Defaults to "mozilla".
|
Defaults to "mozilla".
|
||||||
|
|
|
@ -595,6 +595,48 @@ function serve(arg1, arg2) {
|
||||||
options = { __proto__: null };
|
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 (canOverrideOptions && env) {
|
||||||
|
const delim = env.indexOf("/");
|
||||||
|
if (delim >= 0) {
|
||||||
|
const network = env.slice(0, delim);
|
||||||
|
const address = env.slice(delim + 1);
|
||||||
|
|
||||||
|
switch (network) {
|
||||||
|
case "tcp": {
|
||||||
|
const ipv6Delim = address.indexOf("]");
|
||||||
|
let hostname: string;
|
||||||
|
let port: number;
|
||||||
|
if (ipv6Delim >= 0) {
|
||||||
|
hostname = address.slice(0, ipv6Delim + 1);
|
||||||
|
port = parseInt(address.slice(ipv6Delim + 2));
|
||||||
|
} else {
|
||||||
|
const [hostname_, port_] = address.split(":");
|
||||||
|
hostname = hostname_;
|
||||||
|
port = parseInt(port_);
|
||||||
|
}
|
||||||
|
if (!Number.isSafeInteger(port) || port < 0 || port > 65535) {
|
||||||
|
throw new TypeError(`DENO_SERVE_ADDRESS: Invalid port: ${port}`);
|
||||||
|
}
|
||||||
|
options.hostname = hostname;
|
||||||
|
options.port = port;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case "unix": {
|
||||||
|
options.path = address;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
console.error(`DENO_SERVE_ADDRESS: Invalid network type: ${network}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const wantsHttps = hasTlsKeyPairOptions(options);
|
const wantsHttps = hasTlsKeyPairOptions(options);
|
||||||
const wantsUnix = ObjectHasOwn(options, "path");
|
const wantsUnix = ObjectHasOwn(options, "path");
|
||||||
const signal = options.signal;
|
const signal = options.signal;
|
||||||
|
|
|
@ -54,6 +54,7 @@ os_pipe.workspace = true
|
||||||
pretty_assertions.workspace = true
|
pretty_assertions.workspace = true
|
||||||
regex.workspace = true
|
regex.workspace = true
|
||||||
serde.workspace = true
|
serde.workspace = true
|
||||||
|
tempfile.workspace = true
|
||||||
test_util.workspace = true
|
test_util.workspace = true
|
||||||
tokio.workspace = true
|
tokio.workspace = true
|
||||||
tower-lsp.workspace = true
|
tower-lsp.workspace = true
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
||||||
|
|
||||||
|
use std::io::BufRead;
|
||||||
|
use std::io::BufReader;
|
||||||
use std::io::Read;
|
use std::io::Read;
|
||||||
|
|
||||||
use deno_fetch::reqwest;
|
use deno_fetch::reqwest;
|
||||||
|
@ -92,3 +94,76 @@ async fn deno_serve_no_args() {
|
||||||
child.kill().unwrap();
|
child.kill().unwrap();
|
||||||
child.wait().unwrap();
|
child.wait().unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[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…
Reference in a new issue