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