Skip to content

Commit

Permalink
Tweak how HTTP methods are configured
Browse files Browse the repository at this point in the history
  • Loading branch information
sagebind committed Jul 20, 2019
1 parent 586558b commit cdf18f4
Show file tree
Hide file tree
Showing 3 changed files with 58 additions and 21 deletions.
47 changes: 31 additions & 16 deletions src/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -575,7 +575,7 @@ impl HttpClient {
) -> Result<(curl::easy::Easy2<RequestHandler>, RequestHandlerFuture), Error> {
// Prepare the request plumbing.
let (parts, body) = request.into_parts();
let body_is_empty = body.is_empty();
let has_body = !body.is_empty();
let body_size = body.len();
let (handler, future) = RequestHandler::new(body);

Expand Down Expand Up @@ -671,11 +671,32 @@ impl HttpClient {
// Enable automatic response decompression.
easy.accept_encoding("")?;

// Set the request data according to the request given.
easy.custom_request(parts.method.as_str())?;
// Curl handles HEAD requests differently.
if parts.method == http::Method::HEAD {
easy.nobody(true)?;
// Set the HTTP method to use. Curl ties in behavior with the request
// method, so we need to configure this carefully.
match (parts.method, has_body) {
// Normal GET request.
(http::Method::GET, false) => {
easy.get(true)?;
}
// HEAD requests do not wait for a response payload.
(http::Method::HEAD, has_body) => {
easy.custom_request("HEAD")?;
easy.nobody(true)?;
easy.upload(has_body)?;
}
// POST requests have special redirect behavior.
(http::Method::POST, _) => {
easy.post(true)?;
}
// Normal PUT request.
(http::Method::PUT, _) => {
easy.upload(true)?;
}
// Default case is to either treat request like a GET or PUT.
(method, has_body) => {
easy.custom_request(method.as_str())?;
easy.upload(has_body)?;
}
}

easy.url(&parts.uri.to_string())?;
Expand All @@ -687,16 +708,10 @@ impl HttpClient {
}
easy.http_headers(headers)?;

// If the request body is non-empty, tell curl that we are going to
// upload something.
if !body_is_empty {
easy.upload(true)?;

if let Some(len) = body_size {
// If we know the size of the request body up front, tell curl
// about it.
easy.in_filesize(len as u64)?;
}
// If we know the size of the request body up front, tell curl
// about it.
if let Some(len) = body_size {
easy.in_filesize(len as u64)?;
}

Ok((easy, future))
Expand Down
20 changes: 20 additions & 0 deletions tests/redirects.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,26 @@ speculate::speculate! {
m2.assert();
}

test "303 redirect changes POST to GET" {
let m1 = mock("POST", "/")
.with_status(303)
.with_header("Location", "/2")
.create();

let m2 = mock("GET", "/2").create();

let response = Request::post(server_url())
.redirect_policy(RedirectPolicy::Follow)
.body(())
.unwrap()
.send()
.unwrap();

assert_eq!(response.status(), 200);
m1.assert();
m2.assert();
}

test "redirect limit is respected" {
let m1 = mock("GET", "/")
.with_status(301)
Expand Down
12 changes: 7 additions & 5 deletions tests/timeouts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ speculate::speculate! {
// Spawn a slow server.
let m = mock("POST", "/")
.with_body_from_fn(|_| {
sleep(Duration::from_millis(500));
sleep(Duration::from_secs(1));
Ok(())
})
.create();
Expand All @@ -26,10 +26,12 @@ speculate::speculate! {
.send();

// Client should time-out.
assert!(match result {
Err(chttp::Error::Timeout) => true,
_ => false,
});
match result {
Err(chttp::Error::Timeout) => {}
e => {
panic!("expected timout error, got {:?}", e);
}
}

m.assert();
}
Expand Down

0 comments on commit cdf18f4

Please sign in to comment.