cookie_monster/cookie/builder.rs
1use std::{
2 borrow::{Borrow, Cow},
3 fmt,
4 time::Duration,
5};
6
7use crate::Cookie;
8
9use super::{expires::Expires, same_site::SameSite};
10
11/// A builder struct for building a [`Cookie`].
12#[derive(PartialEq, Clone)]
13pub struct CookieBuilder(Cookie);
14
15impl CookieBuilder {
16 /// Build a new cookie. This returns a `CookieBuilder` that can be used to set other attribute
17 /// values.
18 ///
19 /// # Example
20 /// ```rust
21 /// use cookie_monster::CookieBuilder;
22 ///
23 /// let cookie = CookieBuilder::new("foo", "bar")
24 /// .secure()
25 /// .http_only()
26 /// .build();
27 ///
28 /// assert!(cookie.secure());
29 /// assert!(cookie.http_only());
30 /// ```
31 #[inline]
32 pub fn new<N, V>(name: N, value: V) -> CookieBuilder
33 where
34 N: Into<Cow<'static, str>>,
35 V: Into<Cow<'static, str>>,
36 {
37 CookieBuilder(Cookie::new(name, value))
38 }
39
40 /// Sets the name of the cookie.
41 #[inline]
42 pub fn name<N: Into<Cow<'static, str>>>(mut self, name: N) -> Self {
43 self.0.set_name(name);
44 self
45 }
46
47 /// Returns the name of the cookie.
48 pub fn get_name(&self) -> &str {
49 self.0.name()
50 }
51
52 /// Sets the value of the cookie.
53 #[inline]
54 pub fn value<V: Into<Cow<'static, str>>>(mut self, value: V) -> Self {
55 self.0.set_value(value);
56 self
57 }
58
59 /// Returns the value of the cookie.
60 pub fn get_value(&self) -> &str {
61 self.0.value()
62 }
63
64 /// Sets the Expires attribute of the cookie.
65 ///
66 /// The argument can be a few different types, based on what features are enabled.
67 ///
68 /// # No features needed
69 ///
70 /// ```rust
71 /// use cookie_monster::{Cookie, Expires};
72 ///
73 /// let cookie = Cookie::build("foo", "bar")
74 /// .expires(Expires::remove())
75 /// .build();
76 ///
77 /// assert!(cookie.expires_is_set());
78 /// ```
79 ///
80 /// # Jiff
81 /// ```rust
82 /// # #[cfg(feature="jiff")]
83 /// # {
84 /// # use cookie_monster::Cookie;
85 /// use jiff::Zoned;
86 ///
87 /// let cookie = Cookie::build("foo", "bar")
88 /// .expires(Zoned::now())
89 /// .build();
90 ///
91 /// # assert!(cookie.expires_is_set());
92 /// # }
93 /// ```
94 ///
95 /// # Chrono
96 /// ```rust
97 /// # #[cfg(feature="chrono")]
98 /// # {
99 /// # use cookie_monster::Cookie;
100 /// use chrono::Utc;
101 ///
102 /// let cookie = Cookie::build("foo", "bar")
103 /// .expires(Utc::now())
104 /// .build();
105 ///
106 /// # assert!(cookie.expires_is_set());
107 /// # }
108 /// ```
109 ///
110 /// # Time
111 /// ```rust
112 /// # #[cfg(feature="time")]
113 /// # {
114 /// # use cookie_monster::Cookie;
115 /// use time::OffsetDateTime;
116 ///
117 /// let cookie = Cookie::build("foo", "bar")
118 /// .expires(OffsetDateTime::now_utc())
119 /// .build();
120 ///
121 /// # assert!(cookie.expires_is_set());
122 /// # }
123 /// ```
124 #[inline]
125 pub fn expires(mut self, expiration: impl Into<Expires>) -> Self {
126 self.0.set_expires(expiration.into());
127 self
128 }
129
130 /// Sets the Max-Age attribute of the cookie.
131 ///
132 /// # Example
133 /// ```rust
134 /// use cookie_monster::Cookie;
135 ///
136 /// let cookie = Cookie::build("foo", "bar")
137 /// .max_age_secs(100)
138 /// .build();
139 ///
140 /// assert_eq!(cookie.max_age_secs(), Some(100));
141 /// ```
142 #[inline]
143 pub fn max_age_secs(mut self, max_age_secs: u64) -> Self {
144 self.0.set_max_age_secs(max_age_secs);
145 self
146 }
147
148 /// Sets the Max-Age attribute of the cookie.
149 ///
150 /// # Example
151 /// ```rust
152 /// use cookie_monster::Cookie;
153 /// use std::time::Duration;
154 ///
155 /// let cookie = Cookie::build("foo", "bar")
156 /// .max_age(Duration::from_secs(100))
157 /// .build();
158 ///
159 /// assert_eq!(cookie.max_age(), Some(Duration::from_secs(100)));
160 /// ```
161 #[inline]
162 pub fn max_age(mut self, max_age: Duration) -> Self {
163 self.0.set_max_age(max_age);
164 self
165 }
166
167 /// Returns the Max-Age attribute of the cookie.
168 pub fn get_max_age(&self) -> Option<Duration> {
169 self.0.max_age()
170 }
171
172 /// Sets the Domain attribute of the cookie.
173 ///
174 /// # Note
175 /// If the domain attribute is set to an empty string or the string contains an invalid cookie
176 /// character, the attribute is ignored.
177 ///
178 /// # Example
179 /// ```rust
180 /// use cookie_monster::Cookie;
181 ///
182 /// let cookie = Cookie::build("foo", "bar")
183 /// .domain("rust-lang.com")
184 /// .build();
185 ///
186 /// assert_eq!(cookie.domain(), Some("rust-lang.com"));
187 /// ```
188 #[inline]
189 pub fn domain<D: Into<Cow<'static, str>>>(mut self, domain: D) -> Self {
190 self.0.set_domain(domain);
191 self
192 }
193
194 /// Sets the Path attribute of the cookie.
195 ///
196 /// # Note
197 /// Not all path value's are allowed by the standard:
198 /// * The path can't be set to and empty string.
199 /// * The path must start with a leading `/`.
200 /// * The path can't contain invalid cookie characters.
201 ///
202 /// If any of these conditions are not met, serializing this cookie returns an error.
203 ///
204 /// # Example
205 /// ```rust
206 /// use cookie_monster::Cookie;
207 ///
208 /// let cookie = Cookie::build("foo", "bar")
209 /// .path("/api/login")
210 /// .build();
211 ///
212 /// assert_eq!(cookie.path(), Some("/api/login"));
213 /// ```
214 #[inline]
215 pub fn path<D: Into<Cow<'static, str>>>(mut self, path: D) -> Self {
216 self.0.set_path(path);
217 self
218 }
219
220 /// Returns the Path attribute of the cookie.
221 pub fn get_path(&self) -> Option<&str> {
222 self.0.path()
223 }
224
225 /// Sets the Secure attribute of the cookie.
226 ///
227 /// # Example
228 /// ```rust
229 /// use cookie_monster::Cookie;
230 ///
231 /// let cookie = Cookie::build("foo", "bar")
232 /// .secure()
233 /// .build();
234 ///
235 /// assert!(cookie.secure());
236 /// ```
237 #[inline]
238 pub fn secure(mut self) -> Self {
239 self.0.set_secure(true);
240 self
241 }
242
243 /// Sets the Secure attribute.
244 #[inline]
245 pub fn set_secure(mut self, secure: bool) -> Self {
246 self.0.set_secure(secure);
247 self
248 }
249
250 /// Sets the HttpOnly attribute of the cookie.
251 ///
252 /// # Example
253 /// ```rust
254 /// use cookie_monster::Cookie;
255 ///
256 /// let cookie = Cookie::build("foo", "bar")
257 /// .http_only()
258 /// .build();
259 ///
260 /// assert!(cookie.http_only());
261 /// ```
262 #[inline]
263 pub fn http_only(mut self) -> Self {
264 self.0.set_http_only(true);
265 self
266 }
267
268 /// Sets the HttpOnly attribute of the cookie.
269 #[inline]
270 pub fn set_http_only(mut self, http_only: bool) -> Self {
271 self.0.set_http_only(http_only);
272 self
273 }
274
275 /// Sets the Partitioned attribute of the cookie. When the partitioned attribute is enabled, the
276 /// secure flag is also enabled while serializing.
277 ///
278 /// <https://developer.mozilla.org/en-US/docs/Web/Privacy/Guides/Privacy_sandbox/Partitioned_cookies>
279 ///
280 /// # Example
281 /// ```rust
282 /// use cookie_monster::Cookie;
283 ///
284 /// let cookie = Cookie::build("foo", "bar")
285 /// .partitioned()
286 /// .build();
287 ///
288 /// assert!(cookie.partitioned());
289 /// ```
290 #[inline]
291 pub fn partitioned(self) -> Self {
292 self.set_partitioned(true)
293 }
294
295 /// Set the Partitioned flag, enabling the Partitioned attribute also enables the Secure Attribute.
296 #[inline]
297 pub fn set_partitioned(mut self, partitioned: bool) -> Self {
298 self.0.set_partitioned(partitioned);
299 self
300 }
301
302 /// Sets the SameSite attribute value of the cookie.
303 ///
304 /// # Example
305 /// ```rust
306 /// use cookie_monster::{Cookie, SameSite};
307 ///
308 /// let cookie = Cookie::build("foo", "bar")
309 /// .same_site(SameSite::Strict)
310 /// .build();
311 ///
312 /// assert_eq!(cookie.same_site(), Some(SameSite::Strict));
313 /// ```
314 #[inline]
315 pub fn same_site<S: Into<Option<SameSite>>>(mut self, same_site: S) -> Self {
316 self.0.set_same_site(same_site);
317 self
318 }
319
320 /// Builds and returns the cookie
321 #[inline]
322 pub fn build(self) -> Cookie {
323 self.0
324 }
325}
326
327impl fmt::Debug for CookieBuilder {
328 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
329 fmt::Debug::fmt(&self.0, f)
330 }
331}
332
333impl fmt::Display for CookieBuilder {
334 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
335 fmt::Display::fmt(&self.0, f)
336 }
337}
338
339impl Borrow<Cookie> for CookieBuilder {
340 fn borrow(&self) -> &Cookie {
341 &self.0
342 }
343}
344
345impl From<CookieBuilder> for Cookie {
346 fn from(value: CookieBuilder) -> Self {
347 value.build()
348 }
349}