mirror of
https://github.com/denoland/deno.git
synced 2024-11-24 15:19:26 -05:00
feat(serve): support --port 0
to use an open port (#23846)
Closes https://github.com/denoland/deno/issues/23845
This commit is contained in:
parent
2b560be83f
commit
20cb0e8863
9 changed files with 96 additions and 16 deletions
1
Cargo.lock
generated
1
Cargo.lock
generated
|
@ -705,6 +705,7 @@ dependencies = [
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"os_pipe",
|
"os_pipe",
|
||||||
"pretty_assertions",
|
"pretty_assertions",
|
||||||
|
"regex",
|
||||||
"serde",
|
"serde",
|
||||||
"test_server",
|
"test_server",
|
||||||
"tokio",
|
"tokio",
|
||||||
|
|
|
@ -26,7 +26,6 @@ use serde::Serialize;
|
||||||
use std::env;
|
use std::env;
|
||||||
use std::ffi::OsString;
|
use std::ffi::OsString;
|
||||||
use std::net::SocketAddr;
|
use std::net::SocketAddr;
|
||||||
use std::num::NonZeroU16;
|
|
||||||
use std::num::NonZeroU32;
|
use std::num::NonZeroU32;
|
||||||
use std::num::NonZeroU8;
|
use std::num::NonZeroU8;
|
||||||
use std::num::NonZeroUsize;
|
use std::num::NonZeroUsize;
|
||||||
|
@ -283,7 +282,7 @@ impl RunFlags {
|
||||||
pub struct ServeFlags {
|
pub struct ServeFlags {
|
||||||
pub script: String,
|
pub script: String,
|
||||||
pub watch: Option<WatchFlagsWithPaths>,
|
pub watch: Option<WatchFlagsWithPaths>,
|
||||||
pub port: NonZeroU16,
|
pub port: u16,
|
||||||
pub host: String,
|
pub host: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -293,7 +292,7 @@ impl ServeFlags {
|
||||||
Self {
|
Self {
|
||||||
script,
|
script,
|
||||||
watch: None,
|
watch: None,
|
||||||
port: NonZeroU16::new(port).unwrap(),
|
port,
|
||||||
host: host.to_owned(),
|
host: host.to_owned(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2464,8 +2463,8 @@ fn serve_subcommand() -> Command {
|
||||||
.arg(
|
.arg(
|
||||||
Arg::new("port")
|
Arg::new("port")
|
||||||
.long("port")
|
.long("port")
|
||||||
.help("The TCP port to serve on, defaulting to 8000.")
|
.help("The TCP port to serve on, defaulting to 8000. Pass 0 to pick a random free port.")
|
||||||
.value_parser(value_parser!(NonZeroU16)),
|
.value_parser(value_parser!(u16)),
|
||||||
)
|
)
|
||||||
.arg(
|
.arg(
|
||||||
Arg::new("host")
|
Arg::new("host")
|
||||||
|
@ -4127,9 +4126,7 @@ fn serve_parse(
|
||||||
app: Command,
|
app: Command,
|
||||||
) -> clap::error::Result<()> {
|
) -> clap::error::Result<()> {
|
||||||
// deno serve implies --allow-net=host:port
|
// deno serve implies --allow-net=host:port
|
||||||
let port = matches
|
let port = matches.remove_one::<u16>("port").unwrap_or(8000);
|
||||||
.remove_one::<NonZeroU16>("port")
|
|
||||||
.unwrap_or(NonZeroU16::new(8000).unwrap());
|
|
||||||
let host = matches
|
let host = matches
|
||||||
.remove_one::<String>("host")
|
.remove_one::<String>("host")
|
||||||
.unwrap_or_else(|| "0.0.0.0".to_owned());
|
.unwrap_or_else(|| "0.0.0.0".to_owned());
|
||||||
|
@ -5322,6 +5319,32 @@ mod tests {
|
||||||
..Flags::default()
|
..Flags::default()
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
let r = flags_from_vec(svec![
|
||||||
|
"deno",
|
||||||
|
"serve",
|
||||||
|
"--port",
|
||||||
|
"0",
|
||||||
|
"--host",
|
||||||
|
"example.com",
|
||||||
|
"main.ts"
|
||||||
|
]);
|
||||||
|
assert_eq!(
|
||||||
|
r.unwrap(),
|
||||||
|
Flags {
|
||||||
|
subcommand: DenoSubcommand::Serve(ServeFlags::new_default(
|
||||||
|
"main.ts".to_string(),
|
||||||
|
0,
|
||||||
|
"example.com"
|
||||||
|
)),
|
||||||
|
permissions: PermissionFlags {
|
||||||
|
allow_net: Some(vec!["example.com:0".to_owned()]),
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
code_cache_enabled: true,
|
||||||
|
..Flags::default()
|
||||||
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
|
@ -62,7 +62,6 @@ use std::env;
|
||||||
use std::io::BufReader;
|
use std::io::BufReader;
|
||||||
use std::io::Cursor;
|
use std::io::Cursor;
|
||||||
use std::net::SocketAddr;
|
use std::net::SocketAddr;
|
||||||
use std::num::NonZeroU16;
|
|
||||||
use std::num::NonZeroUsize;
|
use std::num::NonZeroUsize;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
@ -1036,7 +1035,7 @@ impl CliOptions {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn serve_port(&self) -> Option<NonZeroU16> {
|
pub fn serve_port(&self) -> Option<u16> {
|
||||||
if let DenoSubcommand::Serve(flags) = self.sub_command() {
|
if let DenoSubcommand::Serve(flags) = self.sub_command() {
|
||||||
Some(flags.port)
|
Some(flags.port)
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
||||||
|
|
||||||
use std::num::NonZeroU16;
|
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
@ -148,7 +147,7 @@ struct SharedWorkerState {
|
||||||
disable_deprecated_api_warning: bool,
|
disable_deprecated_api_warning: bool,
|
||||||
verbose_deprecated_api_warning: bool,
|
verbose_deprecated_api_warning: bool,
|
||||||
code_cache: Option<Arc<dyn code_cache::CodeCache>>,
|
code_cache: Option<Arc<dyn code_cache::CodeCache>>,
|
||||||
serve_port: Option<NonZeroU16>,
|
serve_port: Option<u16>,
|
||||||
serve_host: Option<String>,
|
serve_host: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -418,7 +417,7 @@ impl CliMainWorkerFactory {
|
||||||
feature_checker: Arc<FeatureChecker>,
|
feature_checker: Arc<FeatureChecker>,
|
||||||
options: CliMainWorkerOptions,
|
options: CliMainWorkerOptions,
|
||||||
node_ipc: Option<i64>,
|
node_ipc: Option<i64>,
|
||||||
serve_port: Option<NonZeroU16>,
|
serve_port: Option<u16>,
|
||||||
serve_host: Option<String>,
|
serve_host: Option<String>,
|
||||||
enable_future_features: bool,
|
enable_future_features: bool,
|
||||||
disable_deprecated_api_warning: bool,
|
disable_deprecated_api_warning: bool,
|
||||||
|
|
|
@ -4,7 +4,6 @@ use deno_core::v8;
|
||||||
use deno_core::ModuleSpecifier;
|
use deno_core::ModuleSpecifier;
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::num::NonZeroU16;
|
|
||||||
use std::thread;
|
use std::thread;
|
||||||
|
|
||||||
use deno_terminal::colors;
|
use deno_terminal::colors;
|
||||||
|
@ -93,7 +92,7 @@ pub struct BootstrapOptions {
|
||||||
pub future: bool,
|
pub future: bool,
|
||||||
pub mode: WorkerExecutionMode,
|
pub mode: WorkerExecutionMode,
|
||||||
// Used by `deno serve`
|
// Used by `deno serve`
|
||||||
pub serve_port: Option<NonZeroU16>,
|
pub serve_port: Option<u16>,
|
||||||
pub serve_host: Option<String>,
|
pub serve_host: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -198,7 +197,7 @@ impl BootstrapOptions {
|
||||||
self.verbose_deprecated_api_warning,
|
self.verbose_deprecated_api_warning,
|
||||||
self.future,
|
self.future,
|
||||||
self.mode as u8 as _,
|
self.mode as u8 as _,
|
||||||
self.serve_port.map(|x| x.into()).unwrap_or_default(),
|
self.serve_port.unwrap_or_default(),
|
||||||
self.serve_host.as_deref(),
|
self.serve_host.as_deref(),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -52,6 +52,7 @@ hyper-util.workspace = true
|
||||||
once_cell.workspace = true
|
once_cell.workspace = true
|
||||||
os_pipe.workspace = true
|
os_pipe.workspace = true
|
||||||
pretty_assertions.workspace = true
|
pretty_assertions.workspace = true
|
||||||
|
regex.workspace = true
|
||||||
serde.workspace = true
|
serde.workspace = true
|
||||||
test_util.workspace = true
|
test_util.workspace = true
|
||||||
tokio.workspace = true
|
tokio.workspace = true
|
||||||
|
|
|
@ -60,6 +60,8 @@ mod publish;
|
||||||
mod repl;
|
mod repl;
|
||||||
#[path = "run_tests.rs"]
|
#[path = "run_tests.rs"]
|
||||||
mod run;
|
mod run;
|
||||||
|
#[path = "serve_tests.rs"]
|
||||||
|
mod serve;
|
||||||
#[path = "shared_library_tests.rs"]
|
#[path = "shared_library_tests.rs"]
|
||||||
mod shared_library_tests;
|
mod shared_library_tests;
|
||||||
#[path = "task_tests.rs"]
|
#[path = "task_tests.rs"]
|
||||||
|
|
51
tests/integration/serve_tests.rs
Normal file
51
tests/integration/serve_tests.rs
Normal file
|
@ -0,0 +1,51 @@
|
||||||
|
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
||||||
|
|
||||||
|
use std::io::Read;
|
||||||
|
|
||||||
|
use deno_fetch::reqwest;
|
||||||
|
use pretty_assertions::assert_eq;
|
||||||
|
use regex::Regex;
|
||||||
|
use test_util as util;
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn deno_serve_port_0() {
|
||||||
|
let mut child = util::deno_cmd()
|
||||||
|
.current_dir(util::testdata_path())
|
||||||
|
.arg("serve")
|
||||||
|
.arg("--port")
|
||||||
|
.arg("0")
|
||||||
|
.arg("./serve.ts")
|
||||||
|
.stdout_piped()
|
||||||
|
.spawn()
|
||||||
|
.unwrap();
|
||||||
|
let stdout = child.stdout.as_mut().unwrap();
|
||||||
|
let mut buffer = [0; 50];
|
||||||
|
let _read = stdout.read(&mut buffer).unwrap();
|
||||||
|
let msg = std::str::from_utf8(&buffer).unwrap();
|
||||||
|
let port_regex = Regex::new(r"(\d+)").unwrap();
|
||||||
|
let port = port_regex.find(msg).unwrap().as_str();
|
||||||
|
|
||||||
|
let cert = reqwest::Certificate::from_pem(include_bytes!(
|
||||||
|
"../testdata/tls/RootCA.crt"
|
||||||
|
))
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let client = reqwest::Client::builder()
|
||||||
|
.add_root_certificate(cert)
|
||||||
|
.http2_prior_knowledge()
|
||||||
|
.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 --port 0 works!");
|
||||||
|
|
||||||
|
child.kill().unwrap();
|
||||||
|
child.wait().unwrap();
|
||||||
|
}
|
5
tests/testdata/serve.ts
vendored
Normal file
5
tests/testdata/serve.ts
vendored
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
export default {
|
||||||
|
fetch(_req: Request) {
|
||||||
|
return new Response("deno serve --port 0 works!");
|
||||||
|
},
|
||||||
|
};
|
Loading…
Reference in a new issue