reqwest_retry

Trait RetryableStrategy

Source
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 500
  • reqwest_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);
}

Required Methods§

Implementors§