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}