1 
2 /// `Set-Cookie` header, defined [RFC6265](http://tools.ietf.org/html/rfc6265#section-4.1)
3 ///
4 /// The Set-Cookie HTTP response header is used to send cookies from the
5 /// server to the user agent.
6 ///
7 /// Informally, the Set-Cookie response header contains the header name
8 /// "Set-Cookie" followed by a ":" and a cookie.  Each cookie begins with
9 /// a name-value-pair, followed by zero or more attribute-value pairs.
10 ///
11 /// # ABNF
12 ///
13 /// ```text
14 /// set-cookie-header = "Set-Cookie:" SP set-cookie-string
15 /// set-cookie-string = cookie-pair *( ";" SP cookie-av )
16 /// cookie-pair       = cookie-name "=" cookie-value
17 /// cookie-name       = token
18 /// cookie-value      = *cookie-octet / ( DQUOTE *cookie-octet DQUOTE )
19 /// cookie-octet      = %x21 / %x23-2B / %x2D-3A / %x3C-5B / %x5D-7E
20 ///                       ; US-ASCII characters excluding CTLs,
21 ///                       ; whitespace DQUOTE, comma, semicolon,
22 ///                       ; and backslash
23 /// token             = <token, defined in [RFC2616], Section 2.2>
24 ///
25 /// cookie-av         = expires-av / max-age-av / domain-av /
26 ///                    path-av / secure-av / httponly-av /
27 ///                     extension-av
28 /// expires-av        = "Expires=" sane-cookie-date
29 /// sane-cookie-date  = <rfc1123-date, defined in [RFC2616], Section 3.3.1>
30 /// max-age-av        = "Max-Age=" non-zero-digit *DIGIT
31 ///                       ; In practice, both expires-av and max-age-av
32 ///                       ; are limited to dates representable by the
33 ///                       ; user agent.
34 /// non-zero-digit    = %x31-39
35 ///                       ; digits 1 through 9
36 /// domain-av         = "Domain=" domain-value
37 /// domain-value      = <subdomain>
38 ///                       ; defined in [RFC1034], Section 3.5, as
39 ///                       ; enhanced by [RFC1123], Section 2.1
40 /// path-av           = "Path=" path-value
41 /// path-value        = <any CHAR except CTLs or ";">
42 /// secure-av         = "Secure"
43 /// httponly-av       = "HttpOnly"
44 /// extension-av      = <any CHAR except CTLs or ";">
45 /// ```
46 ///
47 /// # Example values
48 ///
49 /// * `SID=31d4d96e407aad42`
50 /// * `lang=en-US; Expires=Wed, 09 Jun 2021 10:18:14 GMT`
51 /// * `lang=; Expires=Sun, 06 Nov 1994 08:49:37 GMT`
52 /// * `lang=en-US; Path=/; Domain=example.com`
53 ///
54 /// # Example
55 #[derive(Clone, Debug)]
56 pub struct SetCookie(Vec<::HeaderValue>);
57 
58 impl ::Header for SetCookie {
name() -> &'static ::HeaderName59     fn name() -> &'static ::HeaderName {
60         &::http::header::SET_COOKIE
61     }
62 
decode<'i, I: Iterator<Item = &'i ::HeaderValue>>(values: &mut I) -> Result<Self, ::Error>63     fn decode<'i, I: Iterator<Item = &'i ::HeaderValue>>(values: &mut I) -> Result<Self, ::Error> {
64         let vec = values
65             .cloned()
66             .collect::<Vec<_>>();
67 
68         if !vec.is_empty() {
69             Ok(SetCookie(vec))
70         } else {
71             Err(::Error::invalid())
72         }
73     }
74 
encode<E: Extend<::HeaderValue>>(&self, values: &mut E)75     fn encode<E: Extend<::HeaderValue>>(&self, values: &mut E) {
76         values.extend(self.0.iter().cloned());
77     }
78 }
79 
80 #[cfg(test)]
81 mod tests {
82     use super::*;
83     use super::super::{test_decode, test_encode};
84 
85     #[test]
decode()86     fn decode() {
87         let set_cookie = test_decode::<SetCookie>(&["foo=bar", "baz=quux"]).unwrap();
88         assert_eq!(set_cookie.0.len(), 2);
89         assert_eq!(set_cookie.0[0], "foo=bar");
90         assert_eq!(set_cookie.0[1], "baz=quux");
91     }
92 
93     #[test]
encode()94     fn encode() {
95         let set_cookie = SetCookie(vec![
96             ::HeaderValue::from_static("foo=bar"),
97             ::HeaderValue::from_static("baz=quux"),
98         ]);
99 
100         let headers = test_encode(set_cookie);
101         let mut vals = headers.get_all("set-cookie").into_iter();
102         assert_eq!(vals.next().unwrap(), "foo=bar");
103         assert_eq!(vals.next().unwrap(), "baz=quux");
104         assert_eq!(vals.next(), None);
105     }
106 }
107