Use cookie_store crate instead of cookie::CookieJar (#169)

CookieJar doesn't support the path-match and domain-match algorithms from [RFC 6265](https://tools.ietf.org/html/rfc6265#section-5.1.3), while cookie_store does.

This fixes some issues with the cookie matching algorithm currently in ureq. For instance,
the domain-match uses substring matching rather than the RFC 6265 algorithm.

This deletes two tests:

match_cookies_returns_nothing_when_no_cookies didn't test much
agent_cookies was failing because cookie_store rejects cookies on the `test:` scheme.
  The way around this is to set up a testserver - but it turns out cookies_on_redirect already
  does that, and covers the same cases and more.

This changes some cookie-related behavior:

 - Cookies could previously be sent to a wrong domain - e.g. a cookie set on `example.com`
  could go to `example.com.evil.com` or `evilexample.com`. Probably no one was relying on
  this, since it's quite broken.
 - A cookie with a path of `/foo` could be sent on a request to `/foobar`, but now it can't.
 - Cookies could previously be set on IP addresses, but now they can't.
 - Cookies could previously be set for domains other than the one on the request (or its
  parents), but now they can't.
 - When a cookie had no domain attribute, it would previously get the domain from the
  request, and subsequently be sent to that domain and all subdomains. Now, it will only
  be sent to that exact domain (host-only).

That last one is probably the most likely to break people, since someone could depend
on it without realizing it was broken behavior.
This commit is contained in:
Jacob Hoffman-Andrews
2020-10-04 10:21:09 -07:00
committed by GitHub
4 changed files with 87 additions and 131 deletions

View File

@@ -31,34 +31,6 @@ fn agent_reuse_headers() {
assert_eq!(resp.header("X-Call").unwrap(), "2");
}
#[cfg(feature = "cookie")]
#[test]
fn agent_cookies() {
let agent = agent();
test::set_handler("/agent_cookies", |_unit| {
test::make_response(
200,
"OK",
vec!["Set-Cookie: foo=bar%20baz; Path=/; HttpOnly"],
vec![],
)
});
agent.get("test://host/agent_cookies").call();
assert!(agent.cookie("foo").is_some());
assert_eq!(agent.cookie("foo").unwrap().value(), "bar baz");
test::set_handler("/agent_cookies", |unit| {
assert!(unit.has("cookie"));
assert_eq!(unit.header("cookie").unwrap(), "foo=bar%20baz");
test::make_response(200, "OK", vec![], vec![])
});
agent.get("test://host/agent_cookies").call();
}
// Handler that answers with a simple HTTP response, and times
// out idle connections after 2 seconds.
fn idle_timeout_handler(mut stream: TcpStream) -> io::Result<()> {