From f5b6bc705947cfe0b421f474e8661f6845d7c8a0 Mon Sep 17 00:00:00 2001 From: Gabriel Lopes Veiga Date: Wed, 27 Aug 2025 03:30:01 +0000 Subject: [PATCH 1/3] Revert "fix: use wss for live reload if on https (#4257)" This reverts commit 956f1836ec32215d0a1d18deeb896a584977dd04. --- leptos/src/hydration/reload_script.js | 4 ---- 1 file changed, 4 deletions(-) diff --git a/leptos/src/hydration/reload_script.js b/leptos/src/hydration/reload_script.js index edf523eea6..11dfa6231f 100644 --- a/leptos/src/hydration/reload_script.js +++ b/leptos/src/hydration/reload_script.js @@ -1,7 +1,3 @@ -if (window.location.protocol === 'https:') { - protocol = 'wss://'; -} - let host = window.location.hostname; let ws = new WebSocket(`${protocol}${host}:${reload_port}/live_reload`); ws.onmessage = (ev) => { From da28aa105296a308cf0d9983d08fcc3579e0e221 Mon Sep 17 00:00:00 2001 From: Gabriel Lopes Veiga Date: Wed, 27 Aug 2025 03:30:27 +0000 Subject: [PATCH 2/3] Reapply "feat: add default "auto" live reload protocol option (#4224)" This reverts commit aedcd5148cb00ea31c9085d43b0202998d66292a. --- leptos/src/hydration/mod.rs | 1 + leptos/src/hydration/reload_script.js | 5 +++++ leptos_config/src/lib.rs | 10 ++++++---- 3 files changed, 12 insertions(+), 4 deletions(-) diff --git a/leptos/src/hydration/mod.rs b/leptos/src/hydration/mod.rs index 60721459fb..e6eda10f12 100644 --- a/leptos/src/hydration/mod.rs +++ b/leptos/src/hydration/mod.rs @@ -27,6 +27,7 @@ pub fn AutoReload( None => options.reload_port, }; let protocol = match options.reload_ws_protocol { + leptos_config::ReloadWSProtocol::Auto => "null", leptos_config::ReloadWSProtocol::WS => "'ws://'", leptos_config::ReloadWSProtocol::WSS => "'wss://'", }; diff --git a/leptos/src/hydration/reload_script.js b/leptos/src/hydration/reload_script.js index 11dfa6231f..a59cce3f95 100644 --- a/leptos/src/hydration/reload_script.js +++ b/leptos/src/hydration/reload_script.js @@ -1,4 +1,9 @@ let host = window.location.hostname; + +if (protocol === null) { + protocol = window.location.protocol === 'https:' ? 'wss://' : 'ws://'; +} + let ws = new WebSocket(`${protocol}${host}:${reload_port}/live_reload`); ws.onmessage = (ev) => { let msg = JSON.parse(ev.data); diff --git a/leptos_config/src/lib.rs b/leptos_config/src/lib.rs index f4d560ec50..2b9e35a147 100644 --- a/leptos_config/src/lib.rs +++ b/leptos_config/src/lib.rs @@ -153,7 +153,7 @@ impl LeptosOptions { None => None, }, reload_ws_protocol: ws_from_str( - env_w_default("LEPTOS_RELOAD_WS_PROTOCOL", "ws")?.as_str(), + env_w_default("LEPTOS_RELOAD_WS_PROTOCOL", "auto")?.as_str(), )?, not_found_path: env_w_default("LEPTOS_NOT_FOUND_PATH", "/404")? .into(), @@ -283,22 +283,24 @@ impl TryFrom for Env { pub enum ReloadWSProtocol { WS, WSS, + Auto, } impl Default for ReloadWSProtocol { fn default() -> Self { - Self::WS + Self::Auto } } fn ws_from_str(input: &str) -> Result { let sanitized = input.to_lowercase(); match sanitized.as_ref() { + "auto" => Ok(ReloadWSProtocol::Auto), "ws" | "WS" => Ok(ReloadWSProtocol::WS), "wss" | "WSS" => Ok(ReloadWSProtocol::WSS), _ => Err(LeptosConfigError::EnvVarError(format!( - "{input} is not a supported websocket protocol. Use only `ws` or \ - `wss`.", + "{input} is not a supported websocket protocol. Use only `auto`, \ + `ws` or `wss`.", ))), } } From 1743f428b11563742582af9fa918e586622167cd Mon Sep 17 00:00:00 2001 From: Gabriel Lopes Veiga Date: Wed, 27 Aug 2025 18:28:26 +0000 Subject: [PATCH 3/3] feat: make config enums non exhaustive --- leptos/src/hydration/mod.rs | 10 ++++++++++ leptos_config/src/lib.rs | 15 ++++++++++++++- leptos_config/src/tests.rs | 14 ++++++++++++++ 3 files changed, 38 insertions(+), 1 deletion(-) diff --git a/leptos/src/hydration/mod.rs b/leptos/src/hydration/mod.rs index e6eda10f12..5e4a5eed1f 100644 --- a/leptos/src/hydration/mod.rs +++ b/leptos/src/hydration/mod.rs @@ -26,10 +26,20 @@ pub fn AutoReload( Some(val) => val, None => options.reload_port, }; + let protocol = match options.reload_ws_protocol { leptos_config::ReloadWSProtocol::Auto => "null", leptos_config::ReloadWSProtocol::WS => "'ws://'", leptos_config::ReloadWSProtocol::WSS => "'wss://'", + + unrecognized => { + leptos::logging::error!( + "Unrecognized live reload protocol option '{}'", + unrecognized, + ); + + "null" + } }; let script = format!( diff --git a/leptos_config/src/lib.rs b/leptos_config/src/lib.rs index 2b9e35a147..fd05db164e 100644 --- a/leptos_config/src/lib.rs +++ b/leptos_config/src/lib.rs @@ -6,7 +6,8 @@ use crate::errors::LeptosConfigError; use config::{Case, Config, File, FileFormat}; use regex::Regex; use std::{ - env::VarError, fs, net::SocketAddr, path::Path, str::FromStr, sync::Arc, + env::VarError, fmt::Display, fs, net::SocketAddr, path::Path, str::FromStr, + sync::Arc, }; use typed_builder::TypedBuilder; @@ -222,6 +223,7 @@ fn env_w_default( /// Setting this to the `PROD` variant will not include the WebSocket code for `cargo-leptos` watch mode. /// Defaults to `DEV`. #[derive(Debug, Clone, serde::Serialize, serde::Deserialize, PartialEq, Eq)] +#[non_exhaustive] pub enum Env { PROD, DEV, @@ -280,6 +282,7 @@ impl TryFrom for Env { /// An enum that can be used to define the websocket protocol Leptos uses for hotreloading /// Defaults to `ws`. #[derive(Debug, Clone, serde::Serialize, serde::Deserialize, PartialEq, Eq)] +#[non_exhaustive] pub enum ReloadWSProtocol { WS, WSS, @@ -335,6 +338,16 @@ impl TryFrom for ReloadWSProtocol { } } +impl Display for ReloadWSProtocol { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + ReloadWSProtocol::WS => f.write_str("ws"), + ReloadWSProtocol::WSS => f.write_str("wss"), + ReloadWSProtocol::Auto => f.write_str("auto"), + } + } +} + /// Loads [LeptosOptions] from a Cargo.toml text content with layered overrides. /// If an env var is specified, like `LEPTOS_ENV`, it will override a setting in the file. pub fn get_config_from_str( diff --git a/leptos_config/src/tests.rs b/leptos_config/src/tests.rs index 9648f0098d..caa096977f 100644 --- a/leptos_config/src/tests.rs +++ b/leptos_config/src/tests.rs @@ -20,6 +20,11 @@ fn env_from_str_test() { #[test] fn ws_from_str_test() { + assert!(matches!( + ws_from_str("auto").unwrap(), + ReloadWSProtocol::Auto + )); + assert!(matches!(ws_from_str("ws").unwrap(), ReloadWSProtocol::WS)); assert!(matches!(ws_from_str("WS").unwrap(), ReloadWSProtocol::WS)); assert!(matches!(ws_from_str("wss").unwrap(), ReloadWSProtocol::WSS)); @@ -28,6 +33,15 @@ fn ws_from_str_test() { assert!(ws_from_str("?").is_err()); } +#[test] +fn ws_from_to_str_test() { + assert_eq!(ws_from_str("auto").unwrap().to_string(), "auto"); + assert_eq!(ws_from_str("ws").unwrap().to_string(), "ws"); + assert_eq!(ws_from_str("WS").unwrap().to_string(), "ws"); + assert_eq!(ws_from_str("wss").unwrap().to_string(), "wss"); + assert_eq!(ws_from_str("WSS").unwrap().to_string(), "wss"); +} + #[test] fn env_w_default_test() { temp_env::with_var("LEPTOS_CONFIG_ENV_TEST", Some("custom"), || {