From d7e9f0c9d82493aae09c25a789759a9ee83b99de Mon Sep 17 00:00:00 2001 From: WindSoilder Date: Tue, 30 Apr 2019 11:00:10 +0800 Subject: [PATCH 1/3] add test for redirect_with_cookie (for now it should fail --- tests/redirect.rs | 53 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/tests/redirect.rs b/tests/redirect.rs index 5bfce95fb..9ff1b6f6f 100644 --- a/tests/redirect.rs +++ b/tests/redirect.rs @@ -387,3 +387,56 @@ fn test_invalid_location_stops_redirect_gh484() { assert_eq!(res.status(), reqwest::StatusCode::FOUND); assert_eq!(res.headers().get(reqwest::header::SERVER).unwrap(), &"test-yikes"); } + +#[test] +fn test_redirect_302_with_set_cookies() { + let code = 302; + let client = reqwest::ClientBuilder::new().cookie_store(true).build().unwrap(); + let server = server! { + request: format!("\ + GET /{} HTTP/1.1\r\n\ + user-agent: $USERAGENT\r\n\ + accept: */*\r\n\ + accept-encoding: gzip\r\n\ + host: $HOST\r\n\ + \r\n\ + ", code), + response: format!("\ + HTTP/1.1 {} reason\r\n\ + Server: test-redirect\r\n\ + Content-Length: 0\r\n\ + Location: /dst\r\n\ + Connection: close\r\n\ + Set-Cookie: key=value\r\n\ + \r\n\ + ", code) + ; + + request: format!("\ + GET /dst HTTP/1.1\r\n\ + user-agent: $USERAGENT\r\n\ + accept: */*\r\n\ + accept-encoding: gzip\r\n\ + referer: http://$HOST/{}\r\n\ + cookie: key=value\r\n\ + host: $HOST\r\n\ + \r\n\ + ", code), + response: b"\ + HTTP/1.1 200 OK\r\n\ + Server: test-dst\r\n\ + Content-Length: 0\r\n\ + \r\n\ + " + }; + + let url = format!("http://{}/{}", server.addr(), code); + let dst = format!("http://{}/{}", server.addr(), "dst"); + let res = client.get(&url) + .send() + .unwrap(); + + assert_eq!(res.url().as_str(), dst); + assert_eq!(res.status(), reqwest::StatusCode::OK); + assert_eq!(res.headers().get(reqwest::header::SERVER).unwrap(), &"test-dst"); +} From f41c159766ba3d6f8b4901cb94d64eee8d9c0b64 Mon Sep 17 00:00:00 2001 From: WindSoilder Date: Tue, 30 Apr 2019 14:12:21 +0800 Subject: [PATCH 2/3] When an request meet 302 with Set-Cookie header, should make request with Cookie header. --- src/async_impl/client.rs | 37 +++++++++++++++++++++++++------------ 1 file changed, 25 insertions(+), 12 deletions(-) diff --git a/src/async_impl/client.rs b/src/async_impl/client.rs index 4b0feaff8..bd46c2d12 100644 --- a/src/async_impl/client.rs +++ b/src/async_impl/client.rs @@ -403,10 +403,10 @@ impl ClientBuilder { } /// Enable a persistent cookie store for the client. - /// - /// Cookies received in responses will be preserved and included in + /// + /// Cookies received in responses will be preserved and included in /// additional requests. - /// + /// /// By default, no cookie store is used. pub fn cookie_store(mut self, enable: bool) -> ClientBuilder { self.config.cookie_store = if enable { @@ -549,15 +549,7 @@ impl Client { if let Some(cookie_store_wrapper) = self.inner.cookie_store.as_ref() { if headers.get(::header::COOKIE).is_none() { let cookie_store = cookie_store_wrapper.read().unwrap(); - let header = cookie_store - .0 - .get_request_cookies(&url) - .map(|c| c.encoded().to_string()) - .collect::>() - .join("; "); - if !header.is_empty() { - headers.insert(::header::COOKIE, HeaderValue::from_bytes(header.as_bytes()).unwrap()); - } + attach_header(&mut headers, &cookie_store, &url); } } @@ -823,6 +815,12 @@ impl Future for PendingRequest { .body(body) .expect("valid request parts"); + // Add cookies from the cookie store. + if let Some(cookie_store_wrapper) = self.client.cookie_store.as_ref() { + let cookie_store = cookie_store_wrapper.read().unwrap(); + attach_header(&mut self.headers, &cookie_store, &self.url); + } + *req.headers_mut() = self.headers.clone(); self.in_flight = self.client.hyper.request(req); continue; @@ -874,3 +872,18 @@ fn make_referer(next: &Url, previous: &Url) -> Option { referer.set_fragment(None); referer.as_str().parse().ok() } + +fn attach_header(headers: &mut HeaderMap, cookie_store: &cookie::CookieStore, url: &Url) { + let header = cookie_store + .0 + .get_request_cookies(url) + .map(|c| c.encoded().to_string()) + .collect::>() + .join("; "); + if !header.is_empty() { + headers.insert( + ::header::COOKIE, + HeaderValue::from_bytes(header.as_bytes()).unwrap() + ); + } +} From 299b68936634ab77dad20266b2efce3f103f0578 Mon Sep 17 00:00:00 2001 From: WindSoilder Date: Wed, 1 May 2019 05:42:47 +0800 Subject: [PATCH 3/3] rename from attach_header to add_cookie_header. --- src/async_impl/client.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/async_impl/client.rs b/src/async_impl/client.rs index bd46c2d12..b8c373372 100644 --- a/src/async_impl/client.rs +++ b/src/async_impl/client.rs @@ -549,7 +549,7 @@ impl Client { if let Some(cookie_store_wrapper) = self.inner.cookie_store.as_ref() { if headers.get(::header::COOKIE).is_none() { let cookie_store = cookie_store_wrapper.read().unwrap(); - attach_header(&mut headers, &cookie_store, &url); + add_cookie_header(&mut headers, &cookie_store, &url); } } @@ -818,7 +818,7 @@ impl Future for PendingRequest { // Add cookies from the cookie store. if let Some(cookie_store_wrapper) = self.client.cookie_store.as_ref() { let cookie_store = cookie_store_wrapper.read().unwrap(); - attach_header(&mut self.headers, &cookie_store, &self.url); + add_cookie_header(&mut self.headers, &cookie_store, &self.url); } *req.headers_mut() = self.headers.clone(); @@ -873,7 +873,7 @@ fn make_referer(next: &Url, previous: &Url) -> Option { referer.as_str().parse().ok() } -fn attach_header(headers: &mut HeaderMap, cookie_store: &cookie::CookieStore, url: &Url) { +fn add_cookie_header(headers: &mut HeaderMap, cookie_store: &cookie::CookieStore, url: &Url) { let header = cookie_store .0 .get_request_cookies(url)