diff --git a/Cargo.lock b/Cargo.lock index 96319e09..4791da0a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1026,9 +1026,9 @@ dependencies = [ [[package]] name = "ureq-proto" -version = "0.1.0" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2334475018d005dc8d946e44cf3200310824943c091cbe5306afadca60ff473c" +checksum = "dcec9cbfbf05a7feef00db0295c6183f468635c7adb12a31e941f3660b071bff" dependencies = [ "http", "httparse", diff --git a/Cargo.toml b/Cargo.toml index 8cb3e048..1ca7e5f5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -38,7 +38,7 @@ _test = [] [dependencies] base64 = "0.22.1" -ureq-proto = "0.1.0" +ureq-proto = "0.2.0" # ureq-proto = { path = "../ureq-proto" } log = "0.4.22" once_cell = "1.19.0" diff --git a/src/lib.rs b/src/lib.rs index c501e5f2..8b1d4971 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -502,6 +502,8 @@ mk_method!(trace, TRACE, WithoutBody); #[cfg(test)] pub(crate) mod test { + use std::io; + use assert_no_alloc::AllocDisabler; use config::Config; use once_cell::sync::Lazy; @@ -717,6 +719,16 @@ pub(crate) mod test { assert_eq!(err.to_string(), "http: invalid uri character"); } + #[test] + fn post_big_body_chunked() { + // https://github.com/algesten/ureq/issues/879 + let mut data = io::Cursor::new(vec![42; 153_600]); + post("http://httpbin.org/post") + .content_type("application/octet-stream") + .send(SendBody::from_reader(&mut data)) + .expect("to send correctly"); + } + #[test] #[cfg(all(feature = "cookies", feature = "_test"))] fn store_response_cookies() { diff --git a/src/run.rs b/src/run.rs index 24a09a63..51d9da3d 100644 --- a/src/run.rs +++ b/src/run.rs @@ -357,7 +357,12 @@ fn send_request( } timings.record_time(Timeout::SendRequest); - Ok(flow.proceed().unwrap()) + + // The request might be misconfigured. + let flow = flow.proceed()?; + + // We checked can_proceed() above, this unwrap is fine. + Ok(flow.unwrap()) } fn await_100( @@ -396,7 +401,11 @@ fn await_100( } timings.record_time(Timeout::Await100); - Ok(flow.proceed()) + + // A misconfigured request might surface here. + let flow = flow.proceed()?; + + Ok(flow) } fn send_body( @@ -416,14 +425,12 @@ fn send_body( let input_len = tmp.len(); - let overhead = flow.calculate_output_overhead(output.len())?; - assert!(input_len > overhead); - let max_input = input_len - overhead; + let input_fitting_in_output = flow.calculate_max_input(output.len()); + let max_input = input_len.min(input_fitting_in_output); - let output_used = if overhead == 0 { - // overhead == 0 means we are not doing chunked transfer. The body can be written - // directly to the output. This optimizes away a memcopy if we were to go via - // flow.write(). + let output_used = if !flow.is_chunked() { + // For non-chunked, The body can be written directly to the output. + // This optimizes away a memcopy if we were to go via flow.write(). let output_used = body.read(output)?; // Size checking is still in the flow.