Skip to content

Commit

Permalink
refactor(header): change Cookie and SetCookie to use String
Browse files Browse the repository at this point in the history
This removes the cookie crate, since it has an optional dependency on
openssl, which can cause massive breakage if toggled on. Instead, the
`Cookie` and `SetCookie` headers now just use a `String`. Anyone can
create any typed header, so it is easy to plug in different
implementations.

BREAKING CHANGE: The `Cookie` and `SetCookie` headers no longer use the
  cookie crate. New headers can be written for any header, or the ones
  provided in hyper can be accessed as strings.
  • Loading branch information
seanmonstar committed Jan 5, 2017
1 parent cb48452 commit f22701f
Show file tree
Hide file tree
Showing 5 changed files with 10 additions and 141 deletions.
4 changes: 0 additions & 4 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,6 @@ typeable = "0.1"
unicase = "1.0"
url = "1.0"

[dependencies.cookie]
version = "0.5"
default-features = false

[dependencies.solicit]
version = "0.4"
default-features = false
Expand Down
69 changes: 5 additions & 64 deletions src/header/common/cookie.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use header::{Header, HeaderFormat, CookiePair, CookieJar};
use header::{Header, HeaderFormat};
use std::fmt::{self, Display};
use std::str::from_utf8;

Expand All @@ -21,7 +21,6 @@ use std::str::from_utf8;
/// # extern crate cookie;
/// # fn main() {
/// use hyper::header::{Headers, Cookie};
/// use cookie::Cookie as CookiePair;
///
/// let mut headers = Headers::new();
///
Expand All @@ -33,9 +32,9 @@ use std::str::from_utf8;
/// # }
/// ```
#[derive(Clone, PartialEq, Debug)]
pub struct Cookie(pub Vec<CookiePair>);
pub struct Cookie(pub Vec<String>);

__hyper__deref!(Cookie => Vec<CookiePair>);
__hyper__deref!(Cookie => Vec<String>);

impl Header for Cookie {
fn header_name() -> &'static str {
Expand All @@ -47,11 +46,7 @@ impl Header for Cookie {
for cookies_raw in raw.iter() {
let cookies_str = try!(from_utf8(&cookies_raw[..]));
for cookie_str in cookies_str.split(';') {
if let Ok(cookie) = cookie_str.trim().parse() {
cookies.push(cookie);
} else {
return Err(::Error::Header);
}
cookies.push(cookie_str.trim().to_owned())
}
}

Expand All @@ -70,64 +65,10 @@ impl HeaderFormat for Cookie {
if i != 0 {
try!(f.write_str("; "));
}
try!(Display::fmt(&cookie.pair(), f));
try!(Display::fmt(&cookie, f));
}
Ok(())
}
}

impl Cookie {
/// This method can be used to create CookieJar that can be used
/// to manipulate cookies and create a corresponding `SetCookie` header afterwards.
pub fn to_cookie_jar(&self, key: &[u8]) -> CookieJar<'static> {
let mut jar = CookieJar::new(key);
for cookie in self.iter() {
jar.add_original(cookie.clone());
}
jar
}

/// Extracts all cookies from `CookieJar` and creates Cookie header.
/// Useful for clients.
pub fn from_cookie_jar(jar: &CookieJar) -> Cookie {
Cookie(jar.iter().collect())
}
}


#[test]
fn test_parse() {
let h = Header::parse_header(&[b"foo=bar; baz=quux".to_vec()][..]);
let c1 = CookiePair::new("foo".to_owned(), "bar".to_owned());
let c2 = CookiePair::new("baz".to_owned(), "quux".to_owned());
assert_eq!(h.ok(), Some(Cookie(vec![c1, c2])));
}

#[test]
fn test_fmt() {
use header::Headers;

let mut cookie_pair = CookiePair::new("foo".to_owned(), "bar".to_owned());
cookie_pair.httponly = true;
cookie_pair.path = Some("/p".to_owned());
let cookie_header = Cookie(vec![
cookie_pair,
CookiePair::new("baz".to_owned(),"quux".to_owned())]);
let mut headers = Headers::new();
headers.set(cookie_header);

assert_eq!(&headers.to_string()[..], "Cookie: foo=bar; baz=quux\r\n");
}

#[test]
fn cookie_jar() {
let cookie_pair = CookiePair::new("foo".to_owned(), "bar".to_owned());
let cookie_header = Cookie(vec![cookie_pair]);
let jar = cookie_header.to_cookie_jar(&[]);
let new_cookie_header = Cookie::from_cookie_jar(&jar);

assert_eq!(cookie_header, new_cookie_header);
}


bench_header!(bench, Cookie, { vec![b"foo=bar; baz=quux".to_vec()] });
75 changes: 5 additions & 70 deletions src/header/common/set_cookie.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use header::{Header, HeaderFormat, CookiePair, CookieJar};
use header::{Header, HeaderFormat};
use std::fmt::{self, Display};
use std::str::from_utf8;

Expand Down Expand Up @@ -61,26 +61,20 @@ use std::str::from_utf8;
/// // extern crate cookie;
///
/// use hyper::header::{Headers, SetCookie};
/// use cookie::Cookie as CookiePair;
///
/// let mut headers = Headers::new();
/// let mut cookie = CookiePair::new("foo".to_owned(), "bar".to_owned());
///
/// cookie.path = Some("/path".to_owned());
/// cookie.domain = Some("example.com".to_owned());
///
/// headers.set(
/// SetCookie(vec![
/// cookie,
/// CookiePair::new("baz".to_owned(), "quux".to_owned()),
/// String::from("foo=bar; Path=/path; Domain=example.com")
/// ])
/// );
/// # }
/// ```
#[derive(Clone, PartialEq, Debug)]
pub struct SetCookie(pub Vec<CookiePair>);
pub struct SetCookie(pub Vec<String>);

__hyper__deref!(SetCookie => Vec<CookiePair>);
__hyper__deref!(SetCookie => Vec<String>);

impl Header for SetCookie {
fn header_name() -> &'static str {
Expand All @@ -91,9 +85,7 @@ impl Header for SetCookie {
let mut set_cookies = Vec::with_capacity(raw.len());
for set_cookies_raw in raw {
if let Ok(s) = from_utf8(&set_cookies_raw[..]) {
if let Ok(cookie) = s.parse() {
set_cookies.push(cookie);
}
set_cookies.push(s.trim().to_owned());
}
}

Expand All @@ -119,60 +111,3 @@ impl HeaderFormat for SetCookie {
}
}


impl SetCookie {
/// Use this to create SetCookie header from CookieJar using
/// calculated delta.
pub fn from_cookie_jar(jar: &CookieJar) -> SetCookie {
SetCookie(jar.delta())
}

/// Use this on client to apply changes from SetCookie to CookieJar.
/// Note that this will `panic!` if `CookieJar` is not root.
pub fn apply_to_cookie_jar(&self, jar: &mut CookieJar) {
for cookie in self.iter() {
jar.add_original(cookie.clone())
}
}
}


#[test]
fn test_parse() {
let h = Header::parse_header(&[b"foo=bar; HttpOnly".to_vec()][..]);
let mut c1 = CookiePair::new("foo".to_owned(), "bar".to_owned());
c1.httponly = true;

assert_eq!(h.ok(), Some(SetCookie(vec![c1])));
}

#[test]
fn test_fmt() {
use header::Headers;

let mut cookie = CookiePair::new("foo".to_owned(), "bar".to_owned());
cookie.httponly = true;
cookie.path = Some("/p".to_owned());
let cookies = SetCookie(vec![cookie, CookiePair::new("baz".to_owned(), "quux".to_owned())]);
let mut headers = Headers::new();
headers.set(cookies);

assert_eq!(
&headers.to_string()[..],
"Set-Cookie: foo=bar; HttpOnly; Path=/p\r\nSet-Cookie: baz=quux\r\n");
}

#[test]
fn cookie_jar() {
let jar = CookieJar::new(b"secret");
let cookie = CookiePair::new("foo".to_owned(), "bar".to_owned());
jar.add(cookie);

let cookies = SetCookie::from_cookie_jar(&jar);

let mut new_jar = CookieJar::new(b"secret");
cookies.apply_to_cookie_jar(&mut new_jar);

assert_eq!(jar.find("foo"), new_jar.find("foo"));
assert_eq!(jar.iter().collect::<Vec<CookiePair>>(), new_jar.iter().collect::<Vec<CookiePair>>());
}
2 changes: 0 additions & 2 deletions src/header/shared/mod.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
pub use self::charset::Charset;
pub use cookie::Cookie as CookiePair;
pub use cookie::CookieJar;
pub use self::encoding::Encoding;
pub use self::entity::EntityTag;
pub use self::httpdate::HttpDate;
Expand Down
1 change: 0 additions & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,6 @@
extern crate rustc_serialize as serialize;
extern crate time;
#[macro_use] extern crate url;
extern crate cookie;
extern crate unicase;
extern crate httparse;
extern crate num_cpus;
Expand Down

0 comments on commit f22701f

Please sign in to comment.