better_auth_api/plugins/test_utils/
cookies.rs1use better_auth_core::utils::cookie_utils::sign_cookie_value_raw;
2use better_auth_core::{AuthContext, AuthSchema, CookieAttributes, SameSite};
3use chrono::Utc;
4use serde::Serialize;
5use std::collections::HashMap;
6
7#[derive(Debug, Clone, Serialize)]
9#[serde(rename_all = "camelCase")]
10pub struct TestCookie {
11 pub name: String,
13 pub value: String,
15 pub domain: String,
17 pub path: String,
19 pub http_only: bool,
21 pub secure: bool,
23 pub same_site: &'static str,
25 #[serde(
27 skip_serializing_if = "Option::is_none",
28 serialize_with = "better_auth_core::wire::serialize_optional_number"
29 )]
30 pub expires: Option<f64>,
31}
32fn signed<S: AuthSchema>(
33 auth: &AuthContext<S>,
34 token: &str,
35) -> (better_auth_core::request_runtime::ResolvedCookie, String) {
36 (
37 auth.config.auth_cookie(
38 "session_token",
39 CookieAttributes {
40 max_age: Some(auth.config.session.expires_in().as_seconds_f64()),
41 ..Default::default()
42 },
43 ),
44 sign_cookie_value_raw(token, &auth.config.secret),
45 )
46}
47pub(super) fn headers<S: AuthSchema>(
48 auth: &AuthContext<S>,
49 token: &str,
50) -> HashMap<String, String> {
51 let (cookie, value) = signed(auth, token);
52 [("cookie".into(), format!("{}={value}", cookie.name))].into()
53}
54pub(super) fn cookies<S: AuthSchema>(
55 auth: &AuthContext<S>,
56 token: &str,
57 domain: Option<&str>,
58) -> Vec<TestCookie> {
59 let (cookie, value) = signed(auth, token);
60 let attributes = cookie.attributes;
61 let domain = domain
62 .filter(|value| !value.is_empty())
63 .map(str::to_owned)
64 .unwrap_or_else(|| {
65 url::Url::parse(auth.base_url())
66 .ok()
67 .and_then(|url| url.host_str().map(str::to_owned))
68 .unwrap_or_else(|| "localhost".into())
69 });
70 vec![TestCookie {
71 name: cookie.name,
72 value,
73 domain,
74 path: attributes
75 .path
76 .filter(|value| !value.is_empty())
77 .unwrap_or_else(|| "/".into()),
78 http_only: attributes.http_only.unwrap_or(true),
79 secure: attributes.secure.unwrap_or(false),
80 same_site: match attributes.same_site {
81 Some(SameSite::Strict) => "Strict",
82 Some(SameSite::None) => "None",
83 _ => "Lax",
84 },
85 expires: attributes
86 .max_age
87 .filter(|value| *value != 0.0 && !value.is_nan())
88 .map(|age| Utc::now().timestamp() as f64 + age),
89 }]
90}