From 395243a539f694d3c6fc98874722cf871dc7603f Mon Sep 17 00:00:00 2001 From: Nikolay Kim Date: Thu, 8 Mar 2018 11:16:54 -0800 Subject: [PATCH] another attempt to fix cookie handling --- CHANGES.md | 2 ++ src/client/request.rs | 12 +++++++++--- src/httprequest.rs | 6 +++++- src/httpresponse.rs | 7 +++---- 4 files changed, 19 insertions(+), 8 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 434904bd9..6a08119ff 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -2,6 +2,8 @@ ## 0.4.6 (2018-03-xx) +* Fix client cookie handling + ## 0.4.5 (2018-03-07) diff --git a/src/client/request.rs b/src/client/request.rs index 1368dc58f..f25492332 100644 --- a/src/client/request.rs +++ b/src/client/request.rs @@ -1,4 +1,5 @@ use std::{fmt, mem}; +use std::fmt::Write as FmtWrite; use std::io::Write; use actix::{Addr, Unsync}; @@ -8,6 +9,7 @@ use http::{uri, HeaderMap, Method, Version, Uri, HttpTryFrom, Error as HttpError use http::header::{self, HeaderName, HeaderValue}; use serde_json; use serde::Serialize; +use percent_encoding::{USERINFO_ENCODE_SET, percent_encode}; use body::Body; use error::Error; @@ -539,10 +541,14 @@ impl ClientRequestBuilder { // set cookies if let Some(ref mut jar) = self.cookies { - for cookie in jar.delta() { - request.headers.append( - header::COOKIE, HeaderValue::from_str(&cookie.to_string()).unwrap()); + let mut cookie = String::new(); + for c in jar.delta() { + let name = percent_encode(c.name().as_bytes(), USERINFO_ENCODE_SET); + let value = percent_encode(c.value().as_bytes(), USERINFO_ENCODE_SET); + let _ = write!(&mut cookie, ";{}={}", name, value); } + request.headers.insert( + header::COOKIE, HeaderValue::from_str(&cookie.as_str()[1..]).unwrap()); } request.body = body.into(); Ok(request) diff --git a/src/httprequest.rs b/src/httprequest.rs index 5b88ec1f5..33926b280 100644 --- a/src/httprequest.rs +++ b/src/httprequest.rs @@ -335,7 +335,11 @@ impl HttpRequest { let mut cookies = Vec::new(); for hdr in msg.headers.get_all(header::COOKIE) { let s = str::from_utf8(hdr.as_bytes()).map_err(CookieParseError::from)?; - cookies.push(Cookie::parse_encoded(s)?.into_owned()); + for cookie_str in s.split(';').map(|s| s.trim()) { + if !cookie_str.is_empty() { + cookies.push(Cookie::parse_encoded(cookie_str)?.into_owned()); + } + } } msg.cookies = Some(cookies) } diff --git a/src/httpresponse.rs b/src/httpresponse.rs index 909b5ceca..9c99d4d68 100644 --- a/src/httpresponse.rs +++ b/src/httpresponse.rs @@ -792,8 +792,8 @@ mod tests { #[test] fn test_response_cookies() { let mut headers = HeaderMap::new(); - headers.insert(COOKIE, HeaderValue::from_static("cookie1=value1; HttpOnly;")); - headers.insert(COOKIE, HeaderValue::from_static("cookie2=value2; HttpOnly;")); + headers.insert(COOKIE, HeaderValue::from_static("cookie1=value1")); + headers.insert(COOKIE, HeaderValue::from_static("cookie2=value2")); let req = HttpRequest::new( Method::GET, Uri::from_str("/").unwrap(), Version::HTTP_11, headers, None); @@ -816,8 +816,7 @@ mod tests { let mut val: Vec<_> = resp.headers().get_all("Set-Cookie") .iter().map(|v| v.to_str().unwrap().to_owned()).collect(); val.sort(); - println!("{:?}", val); - assert!(val[0].starts_with("cookie2=; HttpOnly; Max-Age=0;")); + assert!(val[0].starts_with("cookie2=; Max-Age=0;")); assert_eq!( val[1],"name=value; HttpOnly; Path=/test; Domain=www.rust-lang.org; Max-Age=86400"); }