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