Skip to content

Commit

Permalink
Add support to configure timeout of Expect 100 behaviour
Browse files Browse the repository at this point in the history
`curl 0.4.35` added the option to configure the timeout value that `curl` will wait for when using an `Expect` header before sending the request body.

This commit adds the ability to configure this timeout via the `Configurable` trait within `isahc`.

Fixes sagebind#303
  • Loading branch information
tailrecur committed Mar 11, 2021
1 parent d2830a2 commit 1480660
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 1 deletion.
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ unstable-interceptors = []

[dependencies]
crossbeam-utils = "0.8"
curl = "0.4.34"
curl = "0.4.35"
curl-sys = "0.4.37"
futures-lite = "1.11"
http = "0.2.1"
Expand Down
35 changes: 35 additions & 0 deletions src/config/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,41 @@ pub trait Configurable: request::WithRequestConfig {
})
}

/// Set maximum time to wait for Expect 100 request before sending body.
///
/// `curl` has internal heuristics that trigger the use of a `Expect`
/// header for large enough request bodies where the client first sends the
/// request headers along with an `Expect: 100-continue` header. The server
/// is supposed to validate the headers and respond with a `100` response
/// status code after which `curl` will send the actual request body.
///
/// However, if the server does not respond to the initial request
/// within `CURLOPT_EXPECT_100_TIMEOUT_MS` then `curl` will send the
/// request body anyways.
/// More info: https://curl.se/libcurl/c/CURLOPT_EXPECT_100_TIMEOUT_MS.html
///
/// If not set, a default timeout of 1 second will be used.
///
/// # Examples
///
/// ```no_run
/// use std::time::Duration;
/// let response = Request::post("https://httpbin.org/post")
/// .expect_100_timeout(Duration::from_millis(0)) //Send request body immediately
/// .body(())?
/// .send()?;
///
/// let response = Request::post("https://httpbin.org/post")
/// .expect_100_timeout(Duration::from_millis(100)) //Wait for a maximum of 100ms before sending body
/// .body(())?
/// .send()?;
/// ```
fn expect_100_timeout(self, timeout: Duration) -> Self {
self.with_config(move |config| {
config.expect_100_timeout = Some(timeout);
})
}

/// Configure how the use of HTTP versions should be negotiated with the
/// server.
///
Expand Down
5 changes: 5 additions & 0 deletions src/config/request.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ define_request_config! {
// Used by curl
timeout: Option<Duration>,
connect_timeout: Option<Duration>,
expect_100_timeout: Option<Duration>,
version_negotiation: Option<VersionNegotiation>,
automatic_decompression: Option<bool>,
authentication: Option<Authentication>,
Expand Down Expand Up @@ -102,6 +103,10 @@ impl SetOpt for RequestConfig {
easy.connect_timeout(timeout)?;
}

if let Some(timeout) = self.expect_100_timeout {
easy.expect_100_timeout(timeout)?;
}

if let Some(negotiation) = self.version_negotiation.as_ref() {
negotiation.set_opt(easy)?;
}
Expand Down

0 comments on commit 1480660

Please sign in to comment.