Skip to content

Commit

Permalink
Misc (#51)
Browse files Browse the repository at this point in the history
  • Loading branch information
zakstucke authored Jun 20, 2024
1 parent 608f6d5 commit d3019cc
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 24 deletions.
1 change: 0 additions & 1 deletion .zetch.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion rust/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -160,14 +160,15 @@ rayon = ['dep:rayon']

# Cookie deps depending on wasm or not:
cookies_ssr = [
'chrono',
'dep:http',
'dep:serde_json',
'dep:axum-extra',
'axum-extra/cookie',
'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.
Expand Down
58 changes: 36 additions & 22 deletions rust/bitbazaar/cookies/cookies.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,16 +20,12 @@ pub fn get_cookie<T: for<'a> Deserialize<'a>>(name: &str) -> Option<T> {
}

/// 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<CookieOptions<'_>>) {
// 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.
Expand Down Expand Up @@ -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::<leptos_axum::ResponseOptions>();
let mut cookie = Cookie::build((name, value)).http_only(options.http_only);
if let Some(path) = options.path {
Expand All @@ -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);
Expand All @@ -101,25 +99,31 @@ 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));
}
}
}
}

/// 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<std::time::Duration>,
pub expires: Option<chrono::Duration>,

/// If true, the cookie will only be transmitted over secure protocol as HTTPS.
/// The default value is false.
Expand All @@ -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
Expand All @@ -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:
Expand All @@ -166,7 +178,9 @@ impl<'a> From<CookieOptions<'a>> 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 {
Expand Down

0 comments on commit d3019cc

Please sign in to comment.