Set chunked Transfer-Encoding when using send
Previously, using `.send()` on `Request` would require to set either the Transfer-Encoding or the Content-Length header. In an effort to provide better ergonomics for this library and to avoid making users fall in a not-so obvious pitfall, the library should build a valid Request without asking the user to mess around with the headers. This commit attempts to fix this issue: if the user use `.send()` to provide an unknown sized reader, the chunked Transfer-Encoding will be used. Of course, there are prior checks to ensure we do not override the user wish, like if the user already set a Content-Length or a Transfer-Encoding. This commit fix an edge case where the Content-Length would not be automatically set if the Transfer-Encoding is set but not chunked.
This commit is contained in:
@@ -66,7 +66,7 @@ impl SizedReader {
|
||||
impl Payload {
|
||||
pub fn into_read(self) -> SizedReader {
|
||||
match self {
|
||||
Payload::Empty => SizedReader::new(None, Box::new(empty())),
|
||||
Payload::Empty => SizedReader::new(Some(0), Box::new(empty())),
|
||||
Payload::Text(text, _charset) => {
|
||||
#[cfg(feature = "charset")]
|
||||
let bytes = {
|
||||
|
||||
@@ -47,7 +47,7 @@
|
||||
//! which follows a build pattern. The builders are finished using:
|
||||
//!
|
||||
//! * [`.call()`](struct.Request.html#method.call) without a request body.
|
||||
//! * [`.send()`](struct.Request.html#method.send) with a request body as `Read` (chunked encoding).
|
||||
//! * [`.send()`](struct.Request.html#method.send) with a request body as `Read` (chunked encoding support for non-known sized readers).
|
||||
//! * [`.send_string()`](struct.Request.html#method.send_string) body as string.
|
||||
//! * [`.send_bytes()`](struct.Request.html#method.send_bytes) body as bytes.
|
||||
//! * [`.send_form()`](struct.Request.html#method.send_form) key-value pairs as application/x-www-form-urlencoded.
|
||||
|
||||
@@ -210,8 +210,10 @@ impl Request {
|
||||
|
||||
/// Send data from a reader.
|
||||
///
|
||||
/// This uses [chunked transfer encoding](https://tools.ietf.org/html/rfc7230#section-4.1).
|
||||
/// The caller is responsible for setting the Transfer-Encoding: chunked header.
|
||||
/// If no Content-Length and Transfer-Encoding header has been set, it uses the [chunked transfer encoding](https://tools.ietf.org/html/rfc7230#section-4.1).
|
||||
///
|
||||
/// The caller may set the Content-Length header to the expected byte size of the reader if is
|
||||
/// known.
|
||||
///
|
||||
/// The input from the reader is buffered into chunks of size 16,384, the max size of a TLS fragment.
|
||||
///
|
||||
@@ -222,7 +224,6 @@ impl Request {
|
||||
///
|
||||
/// let resp = ureq::post("http://localhost/example-upload")
|
||||
/// .set("Content-Type", "text/plain")
|
||||
/// .set("Transfer-Encoding", "chunked")
|
||||
/// .send(read);
|
||||
/// ```
|
||||
pub fn send(&mut self, reader: impl Read + 'static) -> Response {
|
||||
|
||||
17
src/unit.rs
17
src/unit.rs
@@ -35,12 +35,12 @@ impl Unit {
|
||||
pub(crate) fn new(req: &Request, url: &Url, mix_queries: bool, body: &SizedReader) -> Self {
|
||||
//
|
||||
|
||||
let is_chunked = req
|
||||
let (is_transfer_encoding_set, mut is_chunked) = req
|
||||
.header("transfer-encoding")
|
||||
// if the user has set an encoding header, obey that.
|
||||
.map(|enc| !enc.is_empty())
|
||||
.map(|enc| (!enc.is_empty(), enc == "chunked"))
|
||||
// otherwise, no chunking.
|
||||
.unwrap_or(false);
|
||||
.unwrap_or((false, false));
|
||||
|
||||
let query_string = combine_query(&url, &req.query, mix_queries);
|
||||
|
||||
@@ -52,9 +52,20 @@ impl Unit {
|
||||
// chunking and Content-Length headers are mutually exclusive
|
||||
// also don't write this if the user has set it themselves
|
||||
if !is_chunked && !req.has("content-length") {
|
||||
// if the payload is of known size (everything beside an unsized reader), set
|
||||
// Content-Length,
|
||||
// otherwise, use the chunked Transfer-Encoding (only if no other Transfer-Encoding
|
||||
// has been set
|
||||
if let Some(size) = body.size {
|
||||
if size != 0 {
|
||||
extra.push(Header::new("Content-Length", &format!("{}", size)));
|
||||
}
|
||||
} else {
|
||||
if !is_transfer_encoding_set {
|
||||
extra.push(Header::new("Transfer-Encoding", "chunked"));
|
||||
is_chunked = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let username = url.username();
|
||||
|
||||
Reference in New Issue
Block a user