Only retry idempotent requests. (#80)

This also reverts a change to send_body that was originally added to
return the number of bytes written. It's no longer needed now that we
check the size of the reader in advance.

Fixes #76.
This commit is contained in:
Jacob Hoffman-Andrews
2020-06-22 09:40:55 -07:00
committed by GitHub
parent 15be014e05
commit 00461fb5bd
4 changed files with 38 additions and 15 deletions

View File

@@ -10,7 +10,7 @@ use url::{form_urlencoded, Url};
use std::fmt;
use crate::agent::{self, Agent, AgentState};
use crate::body::Payload;
use crate::body::{Payload, SizedReader};
use crate::error::Error;
use crate::header::{self, Header};
use crate::pool;
@@ -605,6 +605,22 @@ impl Request {
self.tls_config = Some(TLSClientConfig(tls_config));
self
}
// Returns true if this request, with the provided body, is retryable.
pub(crate) fn is_retryable(&self, body: &SizedReader) -> bool {
// Per https://tools.ietf.org/html/rfc7231#section-8.1.3
// these methods are idempotent.
let idempotent = match self.method.as_str() {
"DELETE" | "GET" | "HEAD" | "OPTIONS" | "PUT" | "TRACE" => true,
_ => false,
};
// Unsized bodies aren't retryable because we can't rewind the reader.
// Sized bodies are retryable only if they are zero-length because of
// coincidences of the current implementation - the function responsible
// for retries doesn't have a way to replay a Payload.
let no_body = body.size.is_none() || body.size.unwrap() > 0;
idempotent && no_body
}
}
#[cfg(feature = "tls")]