#[cfg(any(feature = "ssr", not(target_arch = "wasm32")))]
use leptos::prelude::*;
#[cfg(any(feature = "ssr", not(target_arch = "wasm32")))]
use std::collections::HashMap;
#[cfg(any(feature = "ssr", not(target_arch = "wasm32")))]
#[derive(Clone, Debug)]
pub(crate) struct HydrationStore {
pub(crate) cookies: ArcRwSignal<HashMap<String, String>>,
pub(crate) query: ArcRwSignal<HashMap<String, String>>,
}
#[cfg(any(feature = "ssr", not(target_arch = "wasm32")))]
impl HydrationStore {
fn new() -> Self {
#[cfg(feature = "ssr")]
let mut cookies = HashMap::new();
#[cfg(not(feature = "ssr"))]
let cookies = HashMap::new();
#[cfg(feature = "ssr")]
let mut query = HashMap::new();
#[cfg(not(feature = "ssr"))]
let query = HashMap::new();
#[cfg(feature = "ssr")]
{
use http::header::COOKIE;
use http::request::Parts;
if let Some(parts) = use_context::<Parts>() {
if let Some(c_str) = parts.headers.get(COOKIE).and_then(|h| h.to_str().ok()) {
for part in c_str.split(';') {
let part = part.trim();
if let Some((k, v)) = part.split_once('=') {
cookies.insert(k.trim().to_string(), v.trim().to_string());
}
}
}
if let Some(q_str) = parts.uri.query() {
if let Ok(params) = serde_urlencoded::from_str::<Vec<(String, String)>>(q_str) {
query.extend(params);
}
}
}
}
Self {
cookies: ArcRwSignal::new(cookies),
query: ArcRwSignal::new(query),
}
}
#[cfg(feature = "ssr")]
pub(crate) fn new_from_parts(parts: &http::request::Parts) -> Self {
use http::header::COOKIE;
let mut cookies = HashMap::new();
let mut query = HashMap::new();
if let Some(c_str) = parts.headers.get(COOKIE).and_then(|h| h.to_str().ok()) {
for part in c_str.split(';') {
let part = part.trim();
if let Some((k, v)) = part.split_once('=') {
cookies.insert(k.trim().to_string(), v.trim().to_string());
}
}
}
let query_str = parts
.extensions
.get::<axum::extract::OriginalUri>()
.and_then(|uri| uri.query())
.or_else(|| parts.uri.query());
if let Some(q_str) = query_str {
if let Ok(params) = serde_urlencoded::from_str::<Vec<(String, String)>>(q_str) {
query.extend(params);
}
}
Self {
cookies: ArcRwSignal::new(cookies),
query: ArcRwSignal::new(query),
}
}
}
#[cfg(any(feature = "ssr", not(target_arch = "wasm32")))]
pub(crate) fn get_store() -> HydrationStore {
if let Some(store) = use_context::<HydrationStore>() {
store
} else {
let store = HydrationStore::new();
provide_context(store.clone());
store
}
}
pub fn get_cookie(name: &str) -> Option<String> {
#[cfg(all(target_arch = "wasm32", not(feature = "ssr")))]
{
use leptos::prelude::document;
let cookies = js_sys::Reflect::get(&document(), &wasm_bindgen::JsValue::from_str("cookie"))
.ok()
.and_then(|v| v.as_string())
.unwrap_or_default();
for part in cookies.split(';') {
let part = part.trim();
if let Some((k, v)) = part.split_once('=') {
if k.trim() == name {
return Some(v.trim().to_string());
}
}
}
None
}
#[cfg(any(feature = "ssr", not(target_arch = "wasm32")))]
{
get_store().cookies.read_untracked().get(name).cloned()
}
}
pub fn set_cookie(name: &str, value: &str, options: &str) {
#[cfg(all(target_arch = "wasm32", not(feature = "ssr")))]
{
use leptos::prelude::document;
let cookie = format!("{}={}{}", name, value, options);
let _ = js_sys::Reflect::set(
&document(),
&wasm_bindgen::JsValue::from_str("cookie"),
&wasm_bindgen::JsValue::from_str(&cookie),
);
}
#[cfg(any(feature = "ssr", not(target_arch = "wasm32")))]
{
let _ = options;
get_store().cookies.update(|c| {
c.insert(name.to_string(), value.to_string());
});
#[cfg(feature = "ssr")]
{
use http::header::SET_COOKIE;
use http::HeaderValue;
use leptos_axum::ResponseOptions;
if let Some(res) = use_context::<ResponseOptions>() {
let cookie = format!("{}={}{}", name, value, options);
if let Ok(val) = HeaderValue::from_str(&cookie) {
res.append_header(SET_COOKIE, val);
}
}
}
}
}
pub fn get_query_param(name: &str) -> Option<String> {
#[cfg(all(target_arch = "wasm32", not(feature = "ssr")))]
{
use leptos::prelude::window;
let search = window().location().search().ok().unwrap_or_default();
return web_sys::UrlSearchParams::new_with_str(&search)
.ok()
.and_then(|p| p.get(name));
}
#[cfg(any(feature = "ssr", not(target_arch = "wasm32")))]
{
get_store().query.read_untracked().get(name).cloned()
}
}