diff --git a/cli/args/flags.rs b/cli/args/flags.rs index 65cad2434e..638f4950c0 100644 --- a/cli/args/flags.rs +++ b/cli/args/flags.rs @@ -356,6 +356,7 @@ pub struct ServeFlags { pub port: u16, pub host: String, pub worker_count: Option, + pub open_site: bool, } impl ServeFlags { @@ -367,6 +368,7 @@ impl ServeFlags { port, host: host.to_owned(), worker_count: None, + open_site: false, } } } @@ -3086,6 +3088,11 @@ Start a server defined in server.ts, watching for changes and running on port 50 .long("host") .help("The TCP address to serve on, defaulting to 0.0.0.0 (all interfaces)") .value_parser(serve_host_validator), + ).arg( + Arg::new("open") + .long("open") + .help("Open the browser on the address that the server is running on.") + .action(ArgAction::SetTrue) ) .arg( parallel_arg("multiple server workers") @@ -5285,6 +5292,7 @@ fn serve_parse( let host = matches .remove_one::("host") .unwrap_or_else(|| "0.0.0.0".to_owned()); + let open_site = matches.remove_one::("open").unwrap_or(false); let worker_count = parallel_arg_parse(matches).map(|v| v.get()); @@ -5331,6 +5339,7 @@ fn serve_parse( port, host, worker_count, + open_site, }); Ok(()) diff --git a/cli/tools/serve.rs b/cli/tools/serve.rs index 1d1b2cf6e4..1bf048930b 100644 --- a/cli/tools/serve.rs +++ b/cli/tools/serve.rs @@ -1,5 +1,6 @@ // Copyright 2018-2025 the Deno authors. MIT license. +use std::str::FromStr; use std::sync::Arc; use deno_core::error::AnyError; @@ -46,6 +47,12 @@ pub async fn serve( let worker_factory = Arc::new(factory.create_cli_main_worker_factory().await?); + + if serve_flags.open_site { + let url = resolve_serve_url(serve_flags.host, serve_flags.port); + let _ = open::that_detached(url); + } + let hmr = serve_flags .watch .map(|watch_flags| watch_flags.hmr) @@ -180,3 +187,40 @@ async fn serve_with_watch( .await?; Ok(0) } + +fn resolve_serve_url(host: String, port: u16) -> String { + let host = if matches!(host.as_str(), "0.0.0.0" | "::") { + "127.0.0.1".to_string() + } else if std::net::Ipv6Addr::from_str(&host).is_ok() { + format!("[{}]", host) + } else { + host + }; + if port == 80 { + format!("http://{host}/") + } else { + format!("http://{host}:{port}/") + } +} + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn test_resolve_serve_url() { + assert_eq!( + resolve_serve_url("localhost".to_string(), 80), + "http://localhost/" + ); + assert_eq!( + resolve_serve_url("0.0.0.0".to_string(), 80), + "http://127.0.0.1/" + ); + assert_eq!(resolve_serve_url("::".to_string(), 80), "http://127.0.0.1/"); + assert_eq!( + resolve_serve_url("::".to_string(), 90), + "http://127.0.0.1:90/" + ); + } +}