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    /// Sets the Domain attribute of the cookie.
168    ///
169    /// # Note
170    /// If the domain attribute is set to an empty string or the string contains an invalid cookie
171    /// character, the attribute is ignored.
172    ///
173    /// # Example
174    /// ```rust
175    /// use cookie_monster::Cookie;
176    ///
177    /// let cookie = Cookie::build("foo", "bar")
178    ///     .domain("rust-lang.com")
179    ///     .build();
180    ///
181    /// assert_eq!(cookie.domain(), Some("rust-lang.com"));
182    /// ```
183    #[inline]
184    pub fn domain<D: Into<Cow<'static, str>>>(mut self, domain: D) -> Self {
185        self.0.set_domain(domain);
186        self
187    }
188
189    /// Sets the Path attribute of the cookie.
190    ///
191    /// # Note
192    /// Not all path value's are allowed by the standard:
193    /// * The path can't be set to and empty string.
194    /// * The path must start with a leading `/`.
195    /// * The path can't contain invalid cookie characters.
196    ///
197    /// If any of these conditions are not met, serializing this cookie returns an error.
198    ///
199    /// # Example
200    /// ```rust
201    /// use cookie_monster::Cookie;
202    ///
203    /// let cookie = Cookie::build("foo", "bar")
204    ///     .path("/api/login")
205    ///     .build();
206    ///
207    /// assert_eq!(cookie.path(), Some("/api/login"));
208    /// ```
209    #[inline]
210    pub fn path<D: Into<Cow<'static, str>>>(mut self, path: D) -> Self {
211        self.0.set_path(path);
212        self
213    }
214
215    /// Sets the Secure attribute of the cookie.
216    ///
217    /// # Example
218    /// ```rust
219    /// use cookie_monster::Cookie;
220    ///
221    /// let cookie = Cookie::build("foo", "bar")
222    ///     .secure()
223    ///     .build();
224    ///
225    /// assert!(cookie.secure());
226    /// ```
227    #[inline]
228    pub fn secure(mut self) -> Self {
229        self.0.set_secure(true);
230        self
231    }
232
233    /// Sets the Secure attribute.
234    #[inline]
235    pub fn set_secure(mut self, secure: bool) -> Self {
236        self.0.set_secure(secure);
237        self
238    }
239
240    /// Sets the HttpOnly attribute of the cookie.
241    ///
242    /// # Example
243    /// ```rust
244    /// use cookie_monster::Cookie;
245    ///
246    /// let cookie = Cookie::build("foo", "bar")
247    ///     .http_only()
248    ///     .build();
249    ///
250    /// assert!(cookie.http_only());
251    /// ```
252    #[inline]
253    pub fn http_only(mut self) -> Self {
254        self.0.set_http_only(true);
255        self
256    }
257
258    /// Sets the HttpOnly attribute of the cookie.
259    #[inline]
260    pub fn set_http_only(mut self, http_only: bool) -> Self {
261        self.0.set_http_only(http_only);
262        self
263    }
264
265    /// Sets the Partitioned attribute of the cookie. When the partitioned attribute is enabled, the
266    /// secure flag is also enabled while serializing.
267    ///
268    /// <https://developer.mozilla.org/en-US/docs/Web/Privacy/Guides/Privacy_sandbox/Partitioned_cookies>
269    ///
270    /// # Example
271    /// ```rust
272    /// use cookie_monster::Cookie;
273    ///
274    /// let cookie = Cookie::build("foo", "bar")
275    ///     .partitioned()
276    ///     .build();
277    ///
278    /// assert!(cookie.partitioned());
279    /// ```
280    #[inline]
281    pub fn partitioned(self) -> Self {
282        self.set_partitioned(true)
283    }
284
285    /// Set the Partitioned flag, enabling the Partitioned attribute also enables the Secure Attribute.
286    #[inline]
287    pub fn set_partitioned(mut self, partitioned: bool) -> Self {
288        self.0.set_partitioned(partitioned);
289        self
290    }
291
292    /// Sets the SameSite attribute value of the cookie.
293    ///
294    /// # Example
295    /// ```rust
296    /// use cookie_monster::{Cookie, SameSite};
297    ///
298    /// let cookie = Cookie::build("foo", "bar")
299    ///     .same_site(SameSite::Strict)
300    ///     .build();
301    ///
302    /// assert_eq!(cookie.same_site(), Some(SameSite::Strict));
303    /// ```
304    #[inline]
305    pub fn same_site<S: Into<Option<SameSite>>>(mut self, same_site: S) -> Self {
306        self.0.set_same_site(same_site);
307        self
308    }
309
310    /// Builds and returns the cookie
311    #[inline]
312    pub fn build(self) -> Cookie {
313        self.0
314    }
315}
316
317impl fmt::Debug for CookieBuilder {
318    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
319        fmt::Debug::fmt(&self.0, f)
320    }
321}
322
323impl fmt::Display for CookieBuilder {
324    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
325        fmt::Display::fmt(&self.0, f)
326    }
327}
328
329impl Borrow<Cookie> for CookieBuilder {
330    fn borrow(&self) -> &Cookie {
331        &self.0
332    }
333}
334
335impl From<CookieBuilder> for Cookie {
336    fn from(value: CookieBuilder) -> Self {
337        value.build()
338    }
339}