mirror of
https://github.com/denoland/deno.git
synced 2024-11-22 04:51:22 +00:00
feat(serve): env var DENO_SERVE_ADDRESS
for configuring default listen address
This commit is contained in:
parent
f4b9d85862
commit
82c97d3fd4
1
Cargo.lock
generated
1
Cargo.lock
generated
@ -744,6 +744,7 @@ dependencies = [
|
||||
"pretty_assertions",
|
||||
"regex",
|
||||
"serde",
|
||||
"tempfile",
|
||||
"test_server",
|
||||
"tokio",
|
||||
"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
|
||||
available
|
||||
|
||||
<g>DENO_SERVE_ADDRESS</> Default listening address for `Deno.serve()`
|
||||
|
||||
<g>DENO_TLS_CA_STORE</> Comma-separated list of order dependent certificate
|
||||
stores. Possible values: "system", "mozilla".
|
||||
Defaults to "mozilla".
|
||||
|
@ -595,6 +595,48 @@ 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 (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 wantsUnix = ObjectHasOwn(options, "path");
|
||||
const signal = options.signal;
|
||||
|
@ -54,6 +54,7 @@ os_pipe.workspace = true
|
||||
pretty_assertions.workspace = true
|
||||
regex.workspace = true
|
||||
serde.workspace = true
|
||||
tempfile.workspace = true
|
||||
test_util.workspace = true
|
||||
tokio.workspace = true
|
||||
tower-lsp.workspace = true
|
||||
|
@ -1,5 +1,7 @@
|
||||
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
||||
|
||||
use std::io::BufRead;
|
||||
use std::io::BufReader;
|
||||
use std::io::Read;
|
||||
|
||||
use deno_fetch::reqwest;
|
||||
@ -92,3 +94,76 @@ async fn deno_serve_no_args() {
|
||||
child.kill().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 New Issue
Block a user