From db93252faf2530d76cf62658d9251987cfaa1b61 Mon Sep 17 00:00:00 2001 From: Miles Murgaw Date: Tue, 11 Jul 2023 00:25:16 -0400 Subject: [PATCH] feat: cli use local certificate --- packages/cli/Cargo.toml | 1 + packages/cli/src/config.rs | 15 ++++++ packages/cli/src/server/mod.rs | 92 ++++++++++++++++++++++++++++------ 3 files changed, 93 insertions(+), 15 deletions(-) diff --git a/packages/cli/Cargo.toml b/packages/cli/Cargo.toml index 7e5e60eed..c947baa63 100644 --- a/packages/cli/Cargo.toml +++ b/packages/cli/Cargo.toml @@ -39,6 +39,7 @@ indicatif = "0.17.0-rc.11" subprocess = "0.2.9" axum = { version = "0.5.1", features = ["ws", "headers"] } +axum-server = { version = "0.5.1", features = ["tls-rustls"] } tower-http = { version = "0.2.2", features = ["full"] } headers = "0.3.7" diff --git a/packages/cli/src/config.rs b/packages/cli/src/config.rs index 6324f725f..4d3da9b65 100644 --- a/packages/cli/src/config.rs +++ b/packages/cli/src/config.rs @@ -77,6 +77,12 @@ impl Default for DioxusConfig { style: Some(vec![]), script: Some(vec![]), }, + https: WebHttpsConfig { + enabled: None, + mkcert: None, + key_path: None, + cert_path: None, + }, }, plugin: toml::Value::Table(toml::map::Map::new()), } @@ -101,6 +107,7 @@ pub struct WebConfig { pub proxy: Option>, pub watcher: WebWatcherConfig, pub resource: WebResourceConfig, + pub https: WebHttpsConfig, } #[derive(Debug, Clone, Serialize, Deserialize)] @@ -134,6 +141,14 @@ pub struct WebDevResourceConfig { pub script: Option>, } +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct WebHttpsConfig { + pub enabled: Option, + pub mkcert: Option, + pub key_path: Option, + pub cert_path: Option, +} + #[derive(Debug, Clone)] pub struct CrateConfig { pub out_dir: PathBuf, diff --git a/packages/cli/src/server/mod.rs b/packages/cli/src/server/mod.rs index 6575875f7..28d38ed04 100644 --- a/packages/cli/src/server/mod.rs +++ b/packages/cli/src/server/mod.rs @@ -10,6 +10,7 @@ use axum::{ routing::{get, get_service}, Router, }; +use axum_server::tls_rustls::RustlsConfig; use cargo_metadata::diagnostic::Diagnostic; use colored::Colorize; use dioxus_core::Template; @@ -84,6 +85,34 @@ pub async fn startup(port: u16, config: CrateConfig, start_browser: bool) -> Res Ok(()) } +/// Returns an enum of rustls config and a bool if mkcert isn't installed +async fn get_rustls(config: &CrateConfig) -> (Option, bool) { + let config = &config.dioxus_config.web.https; + if config.enabled != Some(true) { + return (None, false); + } + + match config.mkcert { + // mkcert, use it + Some(true) => { + todo!() + } + // not mkcert + Some(false) => { + // get paths to cert & key + if let (Some(key), Some(cert)) = (config.key_path.clone(), config.cert_path.clone()) { + let rustls = RustlsConfig::from_pem_file(cert, key).await.unwrap(); + return (Some(rustls), false); + } else { + // missing cert or key + return (None, false); + } + } + // other + _ => return (None, false), + } +} + pub struct HotReloadState { pub messages: broadcast::Sender>, pub build_manager: Arc, @@ -274,6 +303,9 @@ pub async fn startup_hot_reload( } } + // HTTPS + let rustls_config = get_rustls(&config).await; + // start serve dev-server at 0.0.0.0:8080 print_console_info( &ip, @@ -368,13 +400,19 @@ pub async fn startup_hot_reload( let addr = format!("0.0.0.0:{}", port).parse().unwrap(); - let server = axum::Server::bind(&addr).serve(router.into_make_service()); - if start_browser { - let _ = open::that(format!("http://{}", addr)); + if config.dioxus_config.web.https.enabled == Some(true) { + let _ = open::that(format!("https://{}", addr)); + } else { + let _ = open::that(format!("http://{}", addr)); + } } - server.await?; + if let (Some(rustls), _) = rustls_config { + axum_server::bind_rustls(addr, rustls).serve(router.into_make_service()).await?; + } else { + axum::Server::bind(&addr).serve(router.into_make_service()).await?; + } Ok(()) } @@ -457,6 +495,9 @@ pub async fn startup_default( .unwrap(); } + // HTTPS + let rustls_config = get_rustls(&config).await; + // start serve dev-server at 0.0.0.0 print_console_info( &ip, @@ -550,13 +591,20 @@ pub async fn startup_default( .layer(Extension(ws_reload_state)); let addr = format!("0.0.0.0:{}", port).parse().unwrap(); - let server = axum::Server::bind(&addr).serve(router.into_make_service()); if start_browser { - let _ = open::that(format!("http://{}", addr)); + if config.dioxus_config.web.https.enabled == Some(true) { + let _ = open::that(format!("https://{}", addr)); + } else { + let _ = open::that(format!("http://{}", addr)); + } } - server.await?; + if let (Some(rustls), _) = rustls_config { + axum_server::bind_rustls(addr, rustls).serve(router.into_make_service()).await?; + } else { + axum::Server::bind(&addr).serve(router.into_make_service()).await?; + } Ok(()) } @@ -634,14 +682,28 @@ fn print_console_info(ip: &String, port: u16, config: &CrateConfig, options: Pre .bold() ); } - println!( - "\t> Local : {}", - format!("http://localhost:{}/", port).blue() - ); - println!( - "\t> Network : {}", - format!("http://{}:{}/", ip, port).blue() - ); + + if config.dioxus_config.web.https.enabled == Some(true) { + println!( + "\t> Local : {}", + format!("https://localhost:{}/", port).blue() + ); + println!( + "\t> Network : {}", + format!("https://{}:{}/", ip, port).blue() + ); + println!("\t> HTTPS : {}", format!("Enabled").green()); + } else { + println!( + "\t> Local : {}", + format!("http://localhost:{}/", port).blue() + ); + println!( + "\t> Network : {}", + format!("http://{}:{}/", ip, port).blue() + ); + println!("\t> HTTPS : {}", format!("Disabled").red()); + } println!(); println!("\t> Profile : {}", profile.green()); println!("\t> Hot Reload : {}", hot_reload.cyan());