Skip to main content

dx_utils/
lib.rs

1//! Utility functions for [Dioxus](https://dioxuslabs.com/) fullstack apps.
2//!
3//! # Features
4//!
5//! - `server` — enables server-side functionality (HTTP headers via `FullstackContext`).
6//!   This feature is typically activated by your app's `server` feature.
7//!
8//! # Functions
9//!
10//! - [`redirect_external`] — redirect to an external URL, works correctly during
11//!   both SSR and client-side navigation.
12
13/// Redirect to an external URL. Works correctly during both SSR (server-side
14/// rendering) and client-side navigation.
15///
16/// **During SSR**: sets HTTP 302 (Found) status and a `Location` header on the
17/// response via [`FullstackContext`], causing a real HTTP redirect before any
18/// HTML reaches the browser.
19///
20/// **On the client** (post-hydration): uses [`navigator().replace()`] with
21/// [`NavigationTarget::External`] for a client-side navigation.
22///
23/// # Arguments
24///
25/// * `url` - The external URL to redirect to.
26///
27/// # Example
28///
29/// ```rust,ignore
30/// use dioxus::prelude::*;
31/// use dx_utils::redirect_external;
32///
33/// #[component]
34/// fn MyGuard() -> Element {
35///     let auth = use_server_future(|| api::check_auth())?;
36///     let binding = auth.read();
37///     let status = binding.as_ref().and_then(|r| r.as_ref().ok());
38///
39///     if let Some(s) = status {
40///         if !s.authenticated {
41///             redirect_external(&s.login_url);
42///             return rsx! {};
43///         }
44///     }
45///
46///     rsx! { Outlet::<Route> {} }
47/// }
48/// ```
49pub fn redirect_external(url: &str) {
50    #[cfg(feature = "server")]
51    {
52        use dioxus::fullstack::FullstackContext;
53        if let Ok(header_value) = http::HeaderValue::from_str(url) {
54            FullstackContext::commit_http_status(http::StatusCode::FOUND, None);
55            if let Some(ctx) = FullstackContext::current() {
56                ctx.add_response_header(http::header::LOCATION, header_value);
57            }
58        }
59    }
60    #[cfg(not(feature = "server"))]
61    {
62        use dioxus::prelude::*;
63        navigator().replace(NavigationTarget::<String>::External(url.to_string()));
64    }
65}