pub trait RetryableStrategy {
// Required method
fn handle(&self, res: &Result<Response, Error>) -> Option<Retryable>;
}
Expand description
A strategy to create a Retryable
from a Result<reqwest::Response, reqwest_middleware::Error>
A RetryableStrategy
has a single handler
functions.
The result of calling the request could be:
reqwest::Response
In case the request has been sent and received correctly This could however still mean that the server responded with a erroneous response. For example a HTTP statuscode of 500reqwest_middleware::Error
In this case the request actually failed. This could, for example, be caused by a timeout on the connection.
Example:
use reqwest_retry::{default_on_request_failure, policies::ExponentialBackoff, Retryable, RetryableStrategy, RetryTransientMiddleware};
use reqwest::{Request, Response};
use reqwest_middleware::{ClientBuilder, Middleware, Next, Result};
use http::Extensions;
// Log each request to show that the requests will be retried
struct LoggingMiddleware;
#[async_trait::async_trait]
impl Middleware for LoggingMiddleware {
async fn handle(
&self,
req: Request,
extensions: &mut Extensions,
next: Next<'_>,
) -> Result<Response> {
println!("Request started {}", req.url());
let res = next.run(req, extensions).await;
println!("Request finished");
res
}
}
// Just a toy example, retry when the successful response code is 201, else do nothing.
struct Retry201;
impl RetryableStrategy for Retry201 {
fn handle(&self, res: &Result<reqwest::Response>) -> Option<Retryable> {
match res {
// retry if 201
Ok(success) if success.status() == 201 => Some(Retryable::Transient),
// otherwise do not retry a successful request
Ok(success) => None,
// but maybe retry a request failure
Err(error) => default_on_request_failure(error),
}
}
}
#[tokio::main]
async fn main() {
// Exponential backoff with max 2 retries
let retry_policy = ExponentialBackoff::builder()
.build_with_max_retries(2);
// Create the actual middleware, with the exponential backoff and custom retry strategy.
let ret_s = RetryTransientMiddleware::new_with_policy_and_strategy(
retry_policy,
Retry201,
);
let client = ClientBuilder::new(reqwest::Client::new())
// Retry failed requests.
.with(ret_s)
// Log the requests
.with(LoggingMiddleware)
.build();
// Send request which should get a 201 response. So it will be retried
let r = client
.get("https://httpbin.org/status/201")
.send()
.await;
println!("{:?}", r);
// Send request which should get a 200 response. So it will not be retried
let r = client
.get("https://httpbin.org/status/200")
.send()
.await;
println!("{:?}", r);
}