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.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}