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