1use std::time::Duration;
6
7#[derive(Debug, Clone)]
11pub struct SessionConfig {
12 pub cookie_name: String,
14 pub cookie_domain: Option<String>,
16 pub cookie_path: String,
18 pub cookie_secure: bool,
20 pub cookie_http_only: bool,
22 pub cookie_same_site: SameSite,
24 pub ttl: Duration,
26 pub id_length: usize,
28 pub secret_key: Option<String>,
30 pub signed: bool,
32}
33
34#[derive(Debug, Clone, Copy, PartialEq, Eq)]
36pub enum SameSite {
37 Strict,
39 Lax,
41 None,
43}
44
45impl Default for SessionConfig {
46 fn default() -> Self {
47 Self {
48 cookie_name: "session".to_string(),
49 cookie_domain: None,
50 cookie_path: "/".to_string(),
51 cookie_secure: false,
52 cookie_http_only: true,
53 cookie_same_site: SameSite::Lax,
54 ttl: Duration::from_secs(3600),
55 id_length: 32,
56 secret_key: None,
57 signed: false,
58 }
59 }
60}
61
62impl SessionConfig {
63 pub fn new() -> Self {
65 Self::default()
66 }
67
68 pub fn with_cookie_name(mut self, name: impl Into<String>) -> Self {
70 self.cookie_name = name.into();
71 self
72 }
73
74 pub fn with_cookie_domain(mut self, domain: impl Into<String>) -> Self {
76 self.cookie_domain = Some(domain.into());
77 self
78 }
79
80 pub fn with_cookie_path(mut self, path: impl Into<String>) -> Self {
82 self.cookie_path = path.into();
83 self
84 }
85
86 pub fn with_secure(mut self, secure: bool) -> Self {
88 self.cookie_secure = secure;
89 self
90 }
91
92 pub fn with_http_only(mut self, http_only: bool) -> Self {
94 self.cookie_http_only = http_only;
95 self
96 }
97
98 pub fn with_same_site(mut self, same_site: SameSite) -> Self {
100 self.cookie_same_site = same_site;
101 self
102 }
103
104 pub fn with_ttl(mut self, ttl: Duration) -> Self {
106 self.ttl = ttl;
107 self
108 }
109
110 pub fn with_id_length(mut self, length: usize) -> Self {
112 self.id_length = length;
113 self
114 }
115
116 pub fn with_secret_key(mut self, key: impl Into<String>) -> Self {
118 self.secret_key = Some(key.into());
119 self.signed = true;
120 self
121 }
122
123 pub fn signed(mut self, key: impl Into<String>) -> Self {
125 self.secret_key = Some(key.into());
126 self.signed = true;
127 self
128 }
129
130 pub fn unsigned(mut self) -> Self {
132 self.secret_key = None;
133 self.signed = false;
134 self
135 }
136
137 pub fn build_cookie_header(&self, session_id: &str) -> String {
139 let mut parts = vec![format!("{}={}", self.cookie_name, session_id)];
140
141 if let Some(ref domain) = self.cookie_domain {
142 parts.push(format!("Domain={}", domain));
143 }
144
145 parts.push(format!("Path={}", self.cookie_path));
146
147 if self.cookie_secure {
148 parts.push("Secure".to_string());
149 }
150
151 if self.cookie_http_only {
152 parts.push("HttpOnly".to_string());
153 }
154
155 let same_site = match self.cookie_same_site {
156 SameSite::Strict => "Strict",
157 SameSite::Lax => "Lax",
158 SameSite::None => "None",
159 };
160 parts.push(format!("SameSite={}", same_site));
161
162 let max_age = self.ttl.as_secs();
163 parts.push(format!("Max-Age={}", max_age));
164
165 parts.join("; ")
166 }
167}