Skip to main content

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