From 66cdfab719c3b29eb605ef2b5d9881dc10d26eb8 Mon Sep 17 00:00:00 2001 From: Maccesch Date: Sat, 16 Sep 2023 02:51:08 +0100 Subject: [PATCH] added relative urls to use_websocket --- CHANGELOG.md | 1 + src/use_websocket.rs | 60 +++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 58 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8d260e5..6b24ab9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -39,6 +39,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Other Changes 🔥 +- `use_websocket` can use relative urls now - Callbacks in options don't require to be cloneable anymore - Callback in `use_raf_fn` doesn't require to be cloneable anymore - All (!) functions can now be safely called on the server. Specifically this includes the following that diff --git a/src/use_websocket.rs b/src/use_websocket.rs index b8f6575..bf7cd99 100644 --- a/src/use_websocket.rs +++ b/src/use_websocket.rs @@ -74,9 +74,22 @@ use web_sys::{BinaryType, CloseEvent, Event, MessageEvent, WebSocket}; /// # } /// ``` /// +/// ## Relative Paths +/// +/// If the provided `url` is relative, it will be resolved relative to the current page. +/// Urls will be resolved like this: +/// +/// | Current Page | Relative Url | Resolved Url | +/// |--------------------------------|--------------------------|-------------------------------------| +/// | http://example.com/some/where | /api/ws | ws://example.com/api/ws | +/// | https://example.com/some/where | /api/ws | wss://example.com/api/ws | +/// | https://example.com/some/where | api/ws | wss://example.com/some/where/api/ws | +/// | https://example.com/some/where | //otherdomain.com/api/ws | wss://otherdomain.com/api/ws | +/// +/// /// ## Server-Side Rendering /// -/// On the server the returned functions amount to noops. +/// On the server the returned functions amount to no-ops. pub fn use_websocket( url: &str, ) -> UseWebsocketReturn< @@ -98,8 +111,8 @@ pub fn use_websocket_with_options( impl Fn(String) + Clone + 'static, impl Fn(Vec) + Clone, > { - let url = url.to_string(); - + let url = normalize_url(url); + logging::log!("{}", url); let UseWebSocketOptions { on_open, on_message, @@ -419,3 +432,44 @@ where /// Sends binary data pub send_bytes: SendBytesFn, } + +fn normalize_url(url: &str) -> String { + cfg_if! { if #[cfg(feature = "ssr")] { + url.to_string() + } else { + if url.starts_with("ws://") || url.starts_with("wss://") { + url.to_string() + } else if url.starts_with("http://") || url.starts_with("https://") { + url.replacen("http", "ws", 1) + } else if url.starts_with("//") { + format!("{}{}", detect_protocol(), url) + } else if url.starts_with('/') { + format!( + "{}//{}{}", + detect_protocol(), + window().location().host().expect("Host not found"), + url + ) + } else { + let mut path = window().location().pathname().expect("Pathname not found"); + if !path.ends_with('/') { + path.push('/') + } + format!( + "{}//{}{}{}", + detect_protocol(), + window().location().host().expect("Host not found"), + path, + url + ) + } + }} +} + +fn detect_protocol() -> String { + cfg_if! { if #[cfg(feature = "ssr")] { + "ws".to_string() + } else { + window().location().protocol().expect("Protocol not found").replace("http", "ws") + }} +}