diff options
Diffstat (limited to 'third_party/rust/headers/src/common/cookie.rs')
-rw-r--r-- | third_party/rust/headers/src/common/cookie.rs | 205 |
1 files changed, 205 insertions, 0 deletions
diff --git a/third_party/rust/headers/src/common/cookie.rs b/third_party/rust/headers/src/common/cookie.rs new file mode 100644 index 0000000000..211ad58043 --- /dev/null +++ b/third_party/rust/headers/src/common/cookie.rs @@ -0,0 +1,205 @@ +use util::{FlatCsv, SemiColon}; + +/// `Cookie` header, defined in [RFC6265](http://tools.ietf.org/html/rfc6265#section-5.4) +/// +/// If the user agent does attach a Cookie header field to an HTTP +/// request, the user agent must send the cookie-string +/// as the value of the header field. +/// +/// When the user agent generates an HTTP request, the user agent MUST NOT +/// attach more than one Cookie header field. +/// +/// # Example values +/// * `SID=31d4d96e407aad42` +/// * `SID=31d4d96e407aad42; lang=en-US` +/// +#[derive(Clone, Debug)] +pub struct Cookie(FlatCsv<SemiColon>); + +derive_header! { + Cookie(_), + name: COOKIE +} + +impl Cookie { + /// Lookup a value for a cookie name. + /// + /// # Example + /// + /// ``` + /// # extern crate headers; + /// use headers::{Cookie, HeaderMap, HeaderMapExt, HeaderValue}; + /// + /// // Setup the header map with strings... + /// let mut headers = HeaderMap::new(); + /// headers.insert("cookie", HeaderValue::from_static("lang=en-US")); + /// + /// // Parse a `Cookie` so we can play with it... + /// let cookie = headers + /// .typed_get::<Cookie>() + /// .expect("we just inserted a valid Cookie"); + /// + /// assert_eq!(cookie.get("lang"), Some("en-US")); + /// assert_eq!(cookie.get("SID"), None); + /// ``` + pub fn get(&self, name: &str) -> Option<&str> { + self.iter() + .find(|&(key, _)| key == name) + .map(|(_, val)| val) + } + + /// Get the number of key-value pairs this `Cookie` contains. + pub fn len(&self) -> usize { + self.iter().count() + } + + /// Iterator the key-value pairs of this `Cookie` header. + pub fn iter(&self) -> impl Iterator<Item = (&str, &str)> { + self.0.iter().filter_map(|kv| { + let mut iter = kv.splitn(2, '='); + let key = iter.next()?.trim(); + let val = iter.next()?.trim(); + Some((key, val)) + }) + } +} + +/* +impl PartialEq for Cookie { + fn eq(&self, other: &Cookie) -> bool { + if self.0.len() == other.0.len() { + for &(ref k, ref v) in self.0.iter() { + if other.get(k) != Some(v) { + return false; + } + } + true + } else { + false + } + } +} +*/ + +#[cfg(test)] +mod tests { + use super::super::test_decode; + use super::Cookie; + + #[test] + fn test_parse() { + let cookie = test_decode::<Cookie>(&["foo=bar"]).unwrap(); + + assert_eq!(cookie.get("foo"), Some("bar")); + assert_eq!(cookie.get("bar"), None); + } + + #[test] + fn test_multipe_same_name() { + let cookie = test_decode::<Cookie>(&["foo=bar; foo=baz"]).unwrap(); + + assert_eq!(cookie.get("foo"), Some("bar")); + } + + #[test] + fn test_multipe_lines() { + let cookie = test_decode::<Cookie>(&["foo=bar", "lol = cat"]).unwrap(); + + assert_eq!(cookie.get("foo"), Some("bar")); + assert_eq!(cookie.get("lol"), Some("cat")); + } + + /* + #[test] + fn test_set_and_get() { + let mut cookie = Cookie::new(); + cookie.append("foo", "bar"); + cookie.append(String::from("dyn"), String::from("amic")); + + assert_eq!(cookie.get("foo"), Some("bar")); + assert_eq!(cookie.get("dyn"), Some("amic")); + assert!(cookie.get("nope").is_none()); + + cookie.append("foo", "notbar"); + assert_eq!(cookie.get("foo"), Some("bar")); + + cookie.set("foo", "hi"); + assert_eq!(cookie.get("foo"), Some("hi")); + assert_eq!(cookie.get("dyn"), Some("amic")); + } + + #[test] + fn test_eq() { + let mut cookie = Cookie::new(); + let mut cookie2 = Cookie::new(); + + // empty is equal + assert_eq!(cookie, cookie2); + + // left has more params + cookie.append("foo", "bar"); + assert_ne!(cookie, cookie2); + + // same len, different params + cookie2.append("bar", "foo"); + assert_ne!(cookie, cookie2); + + + // right has more params, and matching KV + cookie2.append("foo", "bar"); + assert_ne!(cookie, cookie2); + + // same params, different order + cookie.append("bar", "foo"); + assert_eq!(cookie, cookie2); + } + + #[test] + fn test_parse() { + let mut cookie = Cookie::new(); + + let parsed = Cookie::parse_header(&b"foo=bar".to_vec().into()).unwrap(); + cookie.append("foo", "bar"); + assert_eq!(cookie, parsed); + + let parsed = Cookie::parse_header(&b"foo=bar;".to_vec().into()).unwrap(); + assert_eq!(cookie, parsed); + + let parsed = Cookie::parse_header(&b"foo=bar; baz=quux".to_vec().into()).unwrap(); + cookie.append("baz", "quux"); + assert_eq!(cookie, parsed); + + let parsed = Cookie::parse_header(&b"foo=bar;; baz=quux".to_vec().into()).unwrap(); + assert_eq!(cookie, parsed); + + let parsed = Cookie::parse_header(&b"foo=bar; invalid ; bad; ;; baz=quux".to_vec().into()) + .unwrap(); + assert_eq!(cookie, parsed); + + let parsed = Cookie::parse_header(&b" foo = bar;baz= quux ".to_vec().into()).unwrap(); + assert_eq!(cookie, parsed); + + let parsed = + Cookie::parse_header(&vec![b"foo = bar".to_vec(), b"baz= quux ".to_vec()].into()) + .unwrap(); + assert_eq!(cookie, parsed); + + let parsed = Cookie::parse_header(&b"foo=bar; baz=quux ; empty=".to_vec().into()).unwrap(); + cookie.append("empty", ""); + assert_eq!(cookie, parsed); + + + let mut cookie = Cookie::new(); + + let parsed = Cookie::parse_header(&b"middle=equals=in=the=middle".to_vec().into()).unwrap(); + cookie.append("middle", "equals=in=the=middle"); + assert_eq!(cookie, parsed); + + let parsed = + Cookie::parse_header(&b"middle=equals=in=the=middle; double==2".to_vec().into()) + .unwrap(); + cookie.append("double", "=2"); + assert_eq!(cookie, parsed); + } + */ +} |