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