content length
This commit is contained in:
35
src/conn.rs
35
src/conn.rs
@@ -22,6 +22,12 @@ impl ConnectionPool {
|
|||||||
) -> Result<Response, Error> {
|
) -> Result<Response, Error> {
|
||||||
//
|
//
|
||||||
|
|
||||||
|
let do_chunk = request.header("transfer-encoding")
|
||||||
|
// if the user has set an encoding header, obey that.
|
||||||
|
.map(|enc| enc.len() > 0)
|
||||||
|
// otherwise, no chunking.
|
||||||
|
.unwrap_or(false);
|
||||||
|
|
||||||
let hostname = url.host_str().unwrap_or("localhost"); // is localhost a good alternative?
|
let hostname = url.host_str().unwrap_or("localhost"); // is localhost a good alternative?
|
||||||
let is_secure = url.scheme().eq_ignore_ascii_case("https");
|
let is_secure = url.scheme().eq_ignore_ascii_case("https");
|
||||||
|
|
||||||
@@ -31,13 +37,23 @@ impl ConnectionPool {
|
|||||||
Some(jar) => match_cookies(jar, hostname, url.path(), is_secure),
|
Some(jar) => match_cookies(jar, hostname, url.path(), is_secure),
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let headers = request.headers.iter().chain(cookie_headers.iter());
|
let extra_headers = {
|
||||||
|
let mut extra = vec![];
|
||||||
|
|
||||||
let do_chunk = request.header("transfer-encoding")
|
// chunking and Content-Length headers are mutually exclusive
|
||||||
// if the user has set an encoding header, obey that.
|
// also don't write this if the user has set it themselves
|
||||||
.map(|enc| enc.len() > 0)
|
if !do_chunk && !request.has("content-length") {
|
||||||
// otherwise, no chunking.
|
if let Some(size) = body.size {
|
||||||
.unwrap_or(false);
|
extra.push(format!("Content-Length: {}\r\n", size).parse::<Header>()?);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
extra
|
||||||
|
};
|
||||||
|
let headers = request
|
||||||
|
.headers
|
||||||
|
.iter()
|
||||||
|
.chain(cookie_headers.iter())
|
||||||
|
.chain(extra_headers.iter());
|
||||||
|
|
||||||
// open socket
|
// open socket
|
||||||
let mut stream = match url.scheme() {
|
let mut stream = match url.scheme() {
|
||||||
@@ -56,13 +72,6 @@ impl ConnectionPool {
|
|||||||
for header in headers {
|
for header in headers {
|
||||||
write!(prelude, "{}: {}\r\n", header.name(), header.value())?;
|
write!(prelude, "{}: {}\r\n", header.name(), header.value())?;
|
||||||
}
|
}
|
||||||
// chunking and Content-Length headers are mutually exclusive
|
|
||||||
// also don't write this if the user has set it themselves
|
|
||||||
if !do_chunk && !request.has("content-length") {
|
|
||||||
if let Some(size) = body.size {
|
|
||||||
write!(prelude, "Content-Length: {}\r\n", size)?;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
write!(prelude, "\r\n")?;
|
write!(prelude, "\r\n")?;
|
||||||
|
|
||||||
stream.write_all(&mut prelude[..])?;
|
stream.write_all(&mut prelude[..])?;
|
||||||
|
|||||||
@@ -41,8 +41,8 @@
|
|||||||
//!
|
//!
|
||||||
//! ```
|
//! ```
|
||||||
//! let resp = ureq::post("http://my-server.com/ingest")
|
//! let resp = ureq::post("http://my-server.com/ingest")
|
||||||
//! .set("Transfer-Encoding", "chunked")`
|
//! .set("Transfer-Encoding", "chunked")
|
||||||
//! .send("Hello world");
|
//! .send_str("Hello world");
|
||||||
//! ```
|
//! ```
|
||||||
|
|
||||||
extern crate ascii;
|
extern crate ascii;
|
||||||
|
|||||||
@@ -35,6 +35,16 @@ pub struct Request {
|
|||||||
redirects: u32,
|
redirects: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl ::std::fmt::Debug for Request {
|
||||||
|
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::result::Result<(), ::std::fmt::Error> {
|
||||||
|
write!(
|
||||||
|
f,
|
||||||
|
"Request[{} {}, {}, {:?}]",
|
||||||
|
self.method, self.path, self.query, self.headers
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
enum Payload {
|
enum Payload {
|
||||||
Empty,
|
Empty,
|
||||||
Text(String),
|
Text(String),
|
||||||
|
|||||||
29
src/test/body_send.rs
Normal file
29
src/test/body_send.rs
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
use test;
|
||||||
|
|
||||||
|
use super::super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn content_length_on_str() {
|
||||||
|
test::set_handler("/content_length_on_str", |_req, _url| {
|
||||||
|
test::make_response(200, "OK", vec![], vec![])
|
||||||
|
});
|
||||||
|
let resp = get("test://host/content_length_on_str")
|
||||||
|
.send_str("Hello World!!!");
|
||||||
|
let vec = resp.to_write_vec();
|
||||||
|
let s = String::from_utf8_lossy(&vec);
|
||||||
|
assert!(s.contains("\r\nContent-Length: 14\r\n"))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn content_length_on_json() {
|
||||||
|
test::set_handler("/content_length_on_json", |_req, _url| {
|
||||||
|
test::make_response(200, "OK", vec![], vec![])
|
||||||
|
});
|
||||||
|
let mut json = SerdeMap::new();
|
||||||
|
json.insert("Hello".to_string(), SerdeValue::String("World!!!".to_string()));
|
||||||
|
let resp = get("test://host/content_length_on_json")
|
||||||
|
.send_json(SerdeValue::Object(json));
|
||||||
|
let vec = resp.to_write_vec();
|
||||||
|
let s = String::from_utf8_lossy(&vec);
|
||||||
|
assert!(s.contains("\r\nContent-Length: 20\r\n"))
|
||||||
|
}
|
||||||
@@ -11,6 +11,7 @@ use std::io::Cursor;
|
|||||||
mod agent_test;
|
mod agent_test;
|
||||||
mod auth;
|
mod auth;
|
||||||
mod body_read;
|
mod body_read;
|
||||||
|
mod body_send;
|
||||||
mod simple;
|
mod simple;
|
||||||
|
|
||||||
type RequestHandler = Fn(&Request, &Url) -> Result<Stream, Error> + Send + 'static;
|
type RequestHandler = Fn(&Request, &Url) -> Result<Stream, Error> + Send + 'static;
|
||||||
|
|||||||
Reference in New Issue
Block a user