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