Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Misc #51

Merged
merged 2 commits into from
Jun 20, 2024
Merged

Misc #51

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading