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}