From d3019ccd24e3db1c92751bebb1a1775b58f971dd Mon Sep 17 00:00:00 2001 From: zakstucke <44890343+zakstucke@users.noreply.github.com> Date: Thu, 20 Jun 2024 14:49:50 +0200 Subject: [PATCH] Misc (#51) --- .zetch.lock | 1 - rust/Cargo.toml | 3 +- rust/bitbazaar/cookies/cookies.rs | 58 +++++++++++++++++++------------ 3 files changed, 38 insertions(+), 24 deletions(-) diff --git a/.zetch.lock b/.zetch.lock index b2cc32ab..8b594790 100644 --- a/.zetch.lock +++ b/.zetch.lock @@ -18,6 +18,5 @@ "py_rust/LICENSE.zetch.md": "d2c12e539d357957b950a54a5477c3a9f87bd2b3ee707be7a4db7adaf5aacc2b", "py_rust/README.zetch.md": "56c9b7ccc00d820f75605ed70d8432768ee64d2f84e2d4aa80254c596a9fdc7d", "rust/LICENSE.zetch.md": "d2c12e539d357957b950a54a5477c3a9f87bd2b3ee707be7a4db7adaf5aacc2b", - "rust/README.zetch.md": "56c9b7ccc00d820f75605ed70d8432768ee64d2f84e2d4aa80254c596a9fdc7d" } } \ No newline at end of file diff --git a/rust/Cargo.toml b/rust/Cargo.toml index 572dea3e..ce2d5184 100644 --- a/rust/Cargo.toml +++ b/rust/Cargo.toml @@ -160,6 +160,7 @@ rayon = ['dep:rayon'] # Cookie deps depending on wasm or not: cookies_ssr = [ + 'chrono', 'dep:http', 'dep:serde_json', 'dep:axum-extra', @@ -167,7 +168,7 @@ cookies_ssr = [ 'dep:leptos', 'dep:leptos_axum', ] -cookies_wasm = ['dep:http', 'dep:serde_json', 'dep:wasm-cookies'] +cookies_wasm = ['chrono', 'dep:http', 'dep:serde_json', 'dep:wasm-cookies'] [profile.release] strip = "debuginfo" # Note: true or "symbols" seems to break static c linking e.g. with ffmpeg. diff --git a/rust/bitbazaar/cookies/cookies.rs b/rust/bitbazaar/cookies/cookies.rs index 962f331e..a402a484 100644 --- a/rust/bitbazaar/cookies/cookies.rs +++ b/rust/bitbazaar/cookies/cookies.rs @@ -20,16 +20,12 @@ pub fn get_cookie Deserialize<'a>>(name: &str) -> Option { } /// Delete a cookie if it exists. -pub fn delete_cookie(name: &str) { - // Easiest way to delete is to just set with instant expiry: - set_cookie( - name, - &"", - CookieOptions { - expires: Some(std::time::Duration::from_secs(0)), - ..Default::default() - }, - ); +/// Cookies might not delete if path or domain are different, if not deleting pass the same options. +pub fn delete_cookie(name: &str, options: Option>) { + // Easiest way to delete is to just set with an expiry in the past: + let mut options = options.unwrap_or_default(); + options.expires = Some(chrono::Duration::seconds(-1)); + set_cookie(name, &"", options); } /// Set a new cookie with the given name and serializable value. @@ -82,6 +78,8 @@ pub fn set_cookie_raw(name: &str, value: &str, options: CookieOptions<'_>) { { use axum_extra::extract::cookie::Cookie; + use crate::prelude::*; + let axum_response = leptos::expect_context::(); let mut cookie = Cookie::build((name, value)).http_only(options.http_only); if let Some(path) = options.path { @@ -91,7 +89,7 @@ pub fn set_cookie_raw(name: &str, value: &str, options: CookieOptions<'_>) { cookie = cookie.domain(domain); } if let Some(expires) = options.expires { - cookie = cookie.max_age(time::Duration::seconds(expires.as_secs() as i64)); + cookie = cookie.max_age(time::Duration::milliseconds(expires.num_milliseconds())); } if options.secure { cookie = cookie.secure(true); @@ -101,8 +99,14 @@ pub fn set_cookie_raw(name: &str, value: &str, options: CookieOptions<'_>) { SameSite::Strict => cookie.same_site(axum_extra::extract::cookie::SameSite::Strict), SameSite::None => cookie.same_site(axum_extra::extract::cookie::SameSite::None), }; - if let Ok(cookie) = http::HeaderValue::from_str(&cookie.to_string()) { - axum_response.insert_header(http::header::SET_COOKIE, cookie); + + match http::HeaderValue::from_str(&cookie.to_string()).change_context(AnyErr) { + Ok(cookie) => { + axum_response.append_header(http::header::SET_COOKIE, cookie); + } + Err(e) => { + record_exception("Failed to set cookie.", format!("{:?}", e)); + } } } } @@ -110,16 +114,16 @@ pub fn set_cookie_raw(name: &str, value: &str, options: CookieOptions<'_>) { /// Cookies options (see [https://developer.mozilla.org/en-US/docs/Web/API/Document/cookie](https://developer.mozilla.org/en-US/docs/Web/API/Document/cookie)). /// /// You can create it by calling `CookieOptions::default()`. -#[derive(Default, Clone, Debug)] +#[derive(Clone, Debug)] pub struct CookieOptions<'a> { - /// If `None`, defaults to the current path of the current document location. + /// If `None`, uses the current path, will default to Some("/"). pub path: Option<&'a str>, /// If `None`, defaults to the host portion of the current document location. pub domain: Option<&'a str>, /// If `None`, the cookie will expire at the end of session. - pub expires: Option, + pub expires: Option, /// If true, the cookie will only be transmitted over secure protocol as HTTPS. /// The default value is false. @@ -133,6 +137,19 @@ pub struct CookieOptions<'a> { pub http_only: bool, } +impl<'a> Default for CookieOptions<'a> { + fn default() -> Self { + Self { + path: Some("/"), + domain: None, + expires: None, + secure: false, + same_site: SameSite::Lax, + http_only: false, + } + } +} + /// SameSite value for [CookieOptions](struct.CookieOptions.html). /// /// SameSite prevents the browser from sending the cookie along with cross-site requests @@ -152,11 +169,6 @@ pub enum SameSite { /// The cookie will be sent in all requests - both cross-site and same-site. None, } -impl Default for SameSite { - fn default() -> Self { - Self::Lax - } -} #[cfg(all(target_arch = "wasm32", feature = "cookies_wasm"))] /// Conversion to the wasm_cookies which was originally created from: @@ -166,7 +178,9 @@ impl<'a> From> for wasm_cookies::CookieOptions<'a> { inner.path = options.path; inner.domain = options.domain; if let Some(expires) = options.expires { - inner = inner.expires_after(expires); + inner = inner.expires_after(std::time::Duration::from_secs( + expires.num_seconds().max(0) as u64, + )); } inner.secure = options.secure; inner.same_site = match options.same_site {