diff --git a/Cargo.lock b/Cargo.lock index 13cb7fd..8f591a3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -321,7 +321,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "qstring" -version = "0.5.2" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -468,7 +468,7 @@ dependencies = [ "lazy_static 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "mime_guess 1.8.4 (registry+https://github.com/rust-lang/crates.io-index)", "native-tls 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "qstring 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", + "qstring 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.20 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -556,7 +556,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum phf_generator 0.7.22 (registry+https://github.com/rust-lang/crates.io-index)" = "05a079dd052e7b674d21cb31cbb6c05efd56a2cd2827db7692e2f1a507ebd998" "checksum phf_shared 0.7.22 (registry+https://github.com/rust-lang/crates.io-index)" = "c2261d544c2bb6aa3b10022b0be371b9c7c64f762ef28c6f5d4f1ef6d97b5930" "checksum pkg-config 0.3.11 (registry+https://github.com/rust-lang/crates.io-index)" = "110d5ee3593dbb73f56294327fe5668bcc997897097cbc76b51e7aed3f52452f" -"checksum qstring 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b4d3f5d9b355cd0db9ef4b46075e6dd578bf9700448ca7f3b8af1481b3c495d4" +"checksum qstring 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "b065672875dc3551830af169852799e394361757bc2a5d9739c37815a7800c03" "checksum rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "eba5f8cb59cc50ed56be8880a5c7b496bfd9bd26394e176bc67884094145c2c5" "checksum redox_syscall 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "c214e91d3ecf43e9a4e41e578973adeb14b474f2bee858742d127af75a0112b1" "checksum remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3488ba1b9a2084d38645c4c08276a1752dcbf2c7130d74f1569681ad5d2799c5" diff --git a/Cargo.toml b/Cargo.toml index 3f528b2..f771d43 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,7 +12,7 @@ dns-lookup = "0.9.1" encoding = "0.2" lazy_static = "1" mime_guess = "1" -qstring = "0.5" +qstring = "0.5.3" native-tls = "0.1" serde_json = "1" url = "1.6" diff --git a/README.md b/README.md index 1303354..d2c9fe9 100644 --- a/README.md +++ b/README.md @@ -4,19 +4,6 @@ # UNDER CONSTRUCTION -- [x] Somewhat finished API -- [x] TLS -- [x] Header handling -- [x] Transfer-Encoding: chunked -- [x] Ergonomic JSON handling -- [x] Test harness for end-to-end tests -- [x] Always chunked RFC2616 #3.6 -- [x] Limit read length on Content-Size -- [x] Auth headers -- [x] Repeated headers -- [x] Cookie jar in agent -- [x] Write tests for send body content-length -- [x] Write tests for send body chunked - [ ] Forms with application/x-www-form-urlencoded - [ ] multipart/form-data - [ ] Connection reuse/keep-alive with pool diff --git a/src/conn.rs b/src/conn.rs index 4501361..cdeffef 100644 --- a/src/conn.rs +++ b/src/conn.rs @@ -29,6 +29,11 @@ impl ConnectionPool { .unwrap_or(false); let hostname = url.host_str().unwrap_or("localhost"); // is localhost a good alternative? + let query_string = if request.query.len() > 0 { + format!("{}", request.query) + } else { + "".to_string() + }; let is_secure = url.scheme().eq_ignore_ascii_case("https"); let cookie_headers: Vec<_> = { @@ -65,7 +70,7 @@ impl ConnectionPool { // send the request start + headers let mut prelude: Vec = vec![]; - write!(prelude, "{} {} HTTP/1.1\r\n", method, url.path())?; + write!(prelude, "{} {}{} HTTP/1.1\r\n", method, url.path(), query_string)?; if !request.has("host") { write!(prelude, "Host: {}\r\n", url.host().unwrap())?; } diff --git a/src/request.rs b/src/request.rs index e46a232..5272db7 100644 --- a/src/request.rs +++ b/src/request.rs @@ -72,7 +72,7 @@ impl SizedReader { impl Payload { fn into_read(self) -> SizedReader { match self { - Payload::Empty => SizedReader::new(Some(0), Box::new(empty())), + Payload::Empty => SizedReader::new(None, Box::new(empty())), Payload::Text(s) => { let bytes = s.into_bytes(); let len = bytes.len(); @@ -134,28 +134,28 @@ impl Request { let mut state = self.state.lock().unwrap(); self.to_url() .and_then(|url| { - if state.is_none() { - // create a one off pool/jar. - ConnectionPool::new().connect( - self, - &self.method, - &url, - self.redirects, - None, - payload.into_read(), - ) - } else { - // reuse connection pool. - let state = state.as_mut().unwrap(); - let jar = &mut state.jar; - state.pool.connect( - self, - &self.method, - &url, - self.redirects, - Some(jar), - payload.into_read(), - ) + match state.as_mut() { + None => + // create a one off pool/jar. + ConnectionPool::new().connect( + self, + &self.method, + &url, + self.redirects, + None, + payload.into_read(), + ), + Some(state) => { + let jar = &mut state.jar; + state.pool.connect( + self, + &self.method, + &url, + self.redirects, + Some(jar), + payload.into_read(), + ) + }, } }) .unwrap_or_else(|e| e.into()) diff --git a/src/test/body_send.rs b/src/test/body_send.rs index 881f19f..7c5ba34 100644 --- a/src/test/body_send.rs +++ b/src/test/body_send.rs @@ -14,6 +14,19 @@ fn content_length_on_str() { assert!(s.contains("\r\nContent-Length: 14\r\n")); } +#[test] +fn user_set_content_length_on_str() { + test::set_handler("/user_set_content_length_on_str", |_req, _url| { + test::make_response(200, "OK", vec![], vec![]) + }); + let resp = get("test://host/user_set_content_length_on_str") + .set("Content-Length", "12345") + .send_str("Hello World!!!"); + let vec = resp.to_write_vec(); + let s = String::from_utf8_lossy(&vec); + assert!(s.contains("\r\nContent-Length: 12345\r\n")); +} + #[test] fn content_length_on_json() { test::set_handler("/content_length_on_json", |_req, _url| { diff --git a/src/test/mod.rs b/src/test/mod.rs index 2acd586..1ba6a40 100644 --- a/src/test/mod.rs +++ b/src/test/mod.rs @@ -12,6 +12,7 @@ mod agent_test; mod auth; mod body_read; mod body_send; +mod query_string; mod simple; type RequestHandler = Fn(&Request, &Url) -> Result + Send + 'static; diff --git a/src/test/query_string.rs b/src/test/query_string.rs new file mode 100644 index 0000000..95e5b84 --- /dev/null +++ b/src/test/query_string.rs @@ -0,0 +1,29 @@ +use test; + +use super::super::*; + +#[test] +fn no_query_string() { + test::set_handler("/no_query_string", |_req, _url| { + test::make_response(200, "OK", vec![], vec![]) + }); + let resp = get("test://host/no_query_string") + .call(); + let vec = resp.to_write_vec(); + let s = String::from_utf8_lossy(&vec); + assert!(s.contains("GET /no_query_string HTTP/1.1")) +} + +#[test] +fn escaped_query_string() { + test::set_handler("/escaped_query_string", |_req, _url| { + test::make_response(200, "OK", vec![], vec![]) + }); + let resp = get("test://host/escaped_query_string") + .query("foo", "bar") + .query("baz", "yo lo") + .call(); + let vec = resp.to_write_vec(); + let s = String::from_utf8_lossy(&vec); + assert!(s.contains("GET /escaped_query_string?foo=bar&baz=yo%20lo HTTP/1.1")) +}