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