mirror of
https://github.com/leptos-rs/leptos
synced 2024-09-20 06:21:57 +00:00
feat: add reload websocket configuration and enable env configuration (#1613)
This commit is contained in:
parent
f5b4b97c9b
commit
d9e83121c1
3 changed files with 109 additions and 23 deletions
|
@ -11,14 +11,17 @@ fn autoreload(nonce_str: &str, options: &LeptosOptions) -> String {
|
|||
Some(val) => val,
|
||||
None => options.reload_port,
|
||||
};
|
||||
let protocol = match options.reload_ws_protocol {
|
||||
leptos_config::ReloadWSProtocol::WS => "'ws://'",
|
||||
leptos_config::ReloadWSProtocol::WSS => "'wss://'",
|
||||
};
|
||||
match std::env::var("LEPTOS_WATCH").is_ok() {
|
||||
true => format!(
|
||||
r#"
|
||||
<script crossorigin=""{nonce_str}>(function () {{
|
||||
{}
|
||||
let protocol = window.location.protocol === 'https:' ? 'wss://' : 'ws://';
|
||||
let host = window.location.hostname;
|
||||
let ws = new WebSocket(protocol + host + ':{reload_port}/live_reload');
|
||||
let ws = new WebSocket({protocol} + host + ':{reload_port}/live_reload');
|
||||
ws.onmessage = (ev) => {{
|
||||
let msg = JSON.parse(ev.data);
|
||||
if (msg.all) window.location.reload();
|
||||
|
|
|
@ -61,6 +61,11 @@ pub struct LeptosOptions {
|
|||
#[builder(default)]
|
||||
#[serde(default)]
|
||||
pub reload_external_port: Option<u32>,
|
||||
/// The protocol the Websocket watcher uses on the client: `ws` in most cases, `wss` when behind a reverse https proxy.
|
||||
/// Defaults to `ws`
|
||||
#[builder(default)]
|
||||
#[serde(default)]
|
||||
pub reload_ws_protocol: ReloadWSProtocol,
|
||||
}
|
||||
|
||||
impl LeptosOptions {
|
||||
|
@ -84,7 +89,7 @@ impl LeptosOptions {
|
|||
output_name,
|
||||
site_root: env_w_default("LEPTOS_SITE_ROOT", "target/site")?,
|
||||
site_pkg_dir: env_w_default("LEPTOS_SITE_PKG_DIR", "pkg")?,
|
||||
env: Env::default(),
|
||||
env: env_from_str(env_w_default("LEPTOS_ENV", "DEV")?.as_str())?,
|
||||
site_addr: env_w_default("LEPTOS_SITE_ADDR", "127.0.0.1:3000")?
|
||||
.parse()?,
|
||||
reload_port: env_w_default("LEPTOS_RELOAD_PORT", "3001")?
|
||||
|
@ -95,6 +100,9 @@ impl LeptosOptions {
|
|||
Some(val) => Some(val.parse()?),
|
||||
None => None,
|
||||
},
|
||||
reload_ws_protocol: ws_from_str(
|
||||
env_w_default("LEPTOS_RELOAD_WS_PROTOCOL", "ws")?.as_str(),
|
||||
)?,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -151,45 +159,103 @@ impl Default for Env {
|
|||
}
|
||||
}
|
||||
|
||||
fn from_str(input: &str) -> Result<Env, String> {
|
||||
fn env_from_str(input: &str) -> Result<Env, LeptosConfigError> {
|
||||
let sanitized = input.to_lowercase();
|
||||
match sanitized.as_ref() {
|
||||
"dev" | "development" => Ok(Env::DEV),
|
||||
"prod" | "production" => Ok(Env::PROD),
|
||||
_ => Err(format!(
|
||||
_ => Err(LeptosConfigError::EnvVarError(format!(
|
||||
"{input} is not a supported environment. Use either `dev` or \
|
||||
`production`.",
|
||||
)),
|
||||
))),
|
||||
}
|
||||
}
|
||||
|
||||
impl FromStr for Env {
|
||||
type Err = ();
|
||||
fn from_str(input: &str) -> Result<Self, Self::Err> {
|
||||
from_str(input).or_else(|_| Ok(Self::default()))
|
||||
env_from_str(input).or_else(|_| Ok(Self::default()))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&str> for Env {
|
||||
fn from(str: &str) -> Self {
|
||||
from_str(str).unwrap_or_else(|err| panic!("{}", err))
|
||||
env_from_str(str).unwrap_or_else(|err| panic!("{}", err))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&Result<String, VarError>> for Env {
|
||||
fn from(input: &Result<String, VarError>) -> Self {
|
||||
match input {
|
||||
Ok(str) => from_str(str).unwrap_or_else(|err| panic!("{}", err)),
|
||||
Ok(str) => {
|
||||
env_from_str(str).unwrap_or_else(|err| panic!("{}", err))
|
||||
}
|
||||
Err(_) => Self::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<String> for Env {
|
||||
type Error = String;
|
||||
type Error = LeptosConfigError;
|
||||
|
||||
fn try_from(s: String) -> Result<Self, Self::Error> {
|
||||
from_str(s.as_str())
|
||||
env_from_str(s.as_str())
|
||||
}
|
||||
}
|
||||
|
||||
/// 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)]
|
||||
pub enum ReloadWSProtocol {
|
||||
WS,
|
||||
WSS,
|
||||
}
|
||||
|
||||
impl Default for ReloadWSProtocol {
|
||||
fn default() -> Self {
|
||||
Self::WS
|
||||
}
|
||||
}
|
||||
|
||||
fn ws_from_str(input: &str) -> Result<ReloadWSProtocol, LeptosConfigError> {
|
||||
let sanitized = input.to_lowercase();
|
||||
match sanitized.as_ref() {
|
||||
"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`.",
|
||||
))),
|
||||
}
|
||||
}
|
||||
|
||||
impl FromStr for ReloadWSProtocol {
|
||||
type Err = ();
|
||||
fn from_str(input: &str) -> Result<Self, Self::Err> {
|
||||
ws_from_str(input).or_else(|_| Ok(Self::default()))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&str> for ReloadWSProtocol {
|
||||
fn from(str: &str) -> Self {
|
||||
ws_from_str(str).unwrap_or_else(|err| panic!("{}", err))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&Result<String, VarError>> for ReloadWSProtocol {
|
||||
fn from(input: &Result<String, VarError>) -> Self {
|
||||
match input {
|
||||
Ok(str) => ws_from_str(str).unwrap_or_else(|err| panic!("{}", err)),
|
||||
Err(_) => Self::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<String> for ReloadWSProtocol {
|
||||
type Error = LeptosConfigError;
|
||||
|
||||
fn try_from(s: String) -> Result<Self, Self::Error> {
|
||||
ws_from_str(s.as_str())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,18 +1,31 @@
|
|||
use crate::{env_w_default, env_wo_default, from_str, Env, LeptosOptions};
|
||||
use crate::{
|
||||
env_from_str, env_w_default, env_wo_default, ws_from_str, Env,
|
||||
LeptosOptions, ReloadWSProtocol,
|
||||
};
|
||||
use std::{net::SocketAddr, str::FromStr};
|
||||
|
||||
#[test]
|
||||
fn from_str_env() {
|
||||
assert!(matches!(from_str("dev").unwrap(), Env::DEV));
|
||||
assert!(matches!(from_str("development").unwrap(), Env::DEV));
|
||||
assert!(matches!(from_str("DEV").unwrap(), Env::DEV));
|
||||
assert!(matches!(from_str("DEVELOPMENT").unwrap(), Env::DEV));
|
||||
assert!(matches!(from_str("prod").unwrap(), Env::PROD));
|
||||
assert!(matches!(from_str("production").unwrap(), Env::PROD));
|
||||
assert!(matches!(from_str("PROD").unwrap(), Env::PROD));
|
||||
assert!(matches!(from_str("PRODUCTION").unwrap(), Env::PROD));
|
||||
assert!(from_str("TEST").is_err());
|
||||
assert!(from_str("?").is_err());
|
||||
fn env_from_str_test() {
|
||||
assert!(matches!(env_from_str("dev").unwrap(), Env::DEV));
|
||||
assert!(matches!(env_from_str("development").unwrap(), Env::DEV));
|
||||
assert!(matches!(env_from_str("DEV").unwrap(), Env::DEV));
|
||||
assert!(matches!(env_from_str("DEVELOPMENT").unwrap(), Env::DEV));
|
||||
assert!(matches!(env_from_str("prod").unwrap(), Env::PROD));
|
||||
assert!(matches!(env_from_str("production").unwrap(), Env::PROD));
|
||||
assert!(matches!(env_from_str("PROD").unwrap(), Env::PROD));
|
||||
assert!(matches!(env_from_str("PRODUCTION").unwrap(), Env::PROD));
|
||||
assert!(env_from_str("TEST").is_err());
|
||||
assert!(env_from_str("?").is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn ws_from_str_test() {
|
||||
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));
|
||||
assert!(matches!(ws_from_str("WSS").unwrap(), ReloadWSProtocol::WSS));
|
||||
assert!(ws_from_str("TEST").is_err());
|
||||
assert!(ws_from_str("?").is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -49,6 +62,8 @@ fn try_from_env_test() {
|
|||
std::env::set_var("LEPTOS_SITE_ADDR", "0.0.0.0:80");
|
||||
std::env::set_var("LEPTOS_RELOAD_PORT", "8080");
|
||||
std::env::set_var("LEPTOS_RELOAD_EXTERNAL_PORT", "8080");
|
||||
std::env::set_var("LEPTOS_ENV", "PROD");
|
||||
std::env::set_var("LEPTOS_RELOAD_WS_PROTOCOL", "WSS");
|
||||
|
||||
let config = LeptosOptions::try_from_env().unwrap();
|
||||
assert_eq!(config.output_name, "app_test");
|
||||
|
@ -61,4 +76,6 @@ fn try_from_env_test() {
|
|||
);
|
||||
assert_eq!(config.reload_port, 8080);
|
||||
assert_eq!(config.reload_external_port, Some(8080));
|
||||
assert_eq!(config.env, Env::PROD);
|
||||
assert_eq!(config.reload_ws_protocol, ReloadWSProtocol::WSS)
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue