1use std::borrow::Borrow;
4
5#[derive(Debug, Clone)]
6pub struct Cookie {
7 name: String,
8 value: String,
9 path: String,
10 domain: String,
11 raw_expires: String,
12 max_age: i32,
13 secure: bool,
14 http_only: bool,
15 same_site: SameSite,
16}
17
18#[derive(Debug, Clone)]
19pub enum SameSite {
20 DefaultMode = 0,
21 LaxMode = 1,
22 StrictMode = 2,
23 NoneMode = 3,
24}
25
26impl Cookie {
27 pub fn get_name(&self) -> &str {
28 self.name.as_str()
29 }
30
31 pub fn set_name(&mut self, name: String) {
32 self.name = name;
33 }
34
35 pub fn get_value(&self) -> &str {
36 self.value.as_str()
37 }
38
39 pub fn set_value(&mut self, value: String) {
40 self.value = value;
41 }
42
43 pub fn get_path(&self) -> &str {
44 self.path.as_str()
45 }
46
47 pub fn set_path(&mut self, path: String) {
48 self.path = path;
49 }
50
51 pub fn get_domain(&self) -> &str {
52 self.domain.as_str()
53 }
54
55 pub fn set_domain(&mut self, domain: String) {
56 self.domain = domain;
57 }
58
59 pub fn get_raw_expires(&self) -> &str {
60 self.raw_expires.as_str()
61 }
62
63 pub fn set_raw_expires(&mut self, raw_expires: String) {
64 self.raw_expires = raw_expires;
65 }
66
67 pub fn get_max_age(&self) -> i32 {
68 self.max_age
69 }
70
71 pub fn set_max_age(&mut self, age: i32) {
72 self.max_age = age;
73 }
74
75 pub fn get_secure(&self) -> bool {
76 self.secure
77 }
78
79 pub fn set_secure(&mut self, secure: bool) {
80 self.secure = secure;
81 }
82
83 pub fn get_http_only(&self) -> bool {
84 self.http_only
85 }
86
87 pub fn set_http_only(&mut self, val: bool) {
88 self.http_only = val;
89 }
90
91 pub fn get_same_site(&self) -> &SameSite {
92 self.same_site.borrow()
93 }
94
95 pub fn set_same_site(&mut self, val: SameSite) {
96 self.same_site = val;
97 }
98
99 pub fn marshal(&self) -> String {
100 assert!(self.name.len() > 0, "cookie name must be specified");
101 let mut str = "".to_string();
102 str += format!("{}={}", self.name, self.value).as_str();
103
104 if self.path.len() > 0 {
105 str += format!("; Path={}", self.path).as_str();
106 }
107
108 if self.domain.len() > 0 {
109 str += format!("; Domain={}", self.domain).as_str();
110 }
111
112 if self.raw_expires.len() > 0 {
113 str += format!("; Expires={}", self.raw_expires).as_str();
114 }
115
116 if self.max_age > 0 {
117 str += format!("; Max-Age={}", self.raw_expires).as_str();
118 }
119
120 if self.secure {
121 str += "; Secure";
122 }
123
124 if self.http_only {
125 str += "; HttpOnly";
126 }
127
128 match self.same_site {
129 SameSite::DefaultMode => {}
130 SameSite::LaxMode => str += "; SameSite=Lax",
131 SameSite::StrictMode => str += "; SameSite=Strict",
132 SameSite::NoneMode => str += "; SameSite=None",
133 }
134
135 return str;
136 }
137
138 pub fn unmarshal(str: String) -> Option<Cookie> {
139 let parts: Vec<_> = str.split(";").collect();
140 let kv: Vec<_> = parts[0].trim().split("=").collect();
141 if kv.len() != 2 {
142 return None;
143 }
144 let mut c = Cookie::default();
145 c.set_name(kv[0].to_string());
146 c.set_value(kv[1].to_string());
147
148 for part in parts {
149 let kv: Vec<_> = part.trim().split("=").collect();
150 if kv.len() != 2 {
151 continue;
152 }
153
154 let k = kv[0].to_lowercase();
155 if k == "path" {
156 c.set_path(kv[1].to_string());
157 } else if k == "domain" {
158 c.set_domain(kv[1].to_string());
159 } else if k == "expires" {
160 c.set_raw_expires(kv[1].to_string());
161 } else if k == "max-age" {
162 c.set_max_age(kv[1].to_string().parse::<i32>().unwrap());
163 } else if k == "secure" {
164 c.set_secure(true);
165 } else if k == "httponly" {
166 c.set_http_only(true);
167 } else if k == "samesite" {
168 let v = kv[1].to_lowercase();
169 if v == "lax" {
170 c.set_same_site(SameSite::LaxMode);
171 } else if v == "strict" {
172 c.set_same_site(SameSite::StrictMode);
173 } else if v == "none" {
174 c.set_same_site(SameSite::NoneMode);
175 } else {
176 c.set_same_site(SameSite::DefaultMode);
177 }
178 }
179 }
180
181 return Some(c);
182 }
183}
184
185impl Default for Cookie {
186 fn default() -> Self {
187 Self {
188 name: "".to_string(),
189 value: "".to_string(),
190 path: "".to_string(),
191 domain: "".to_string(),
192 raw_expires: "".to_string(),
193 max_age: 0,
194 secure: false,
195 http_only: false,
196 same_site: SameSite::DefaultMode,
197 }
198 }
199}