1use http::Extensions;
2use reqwest::{Request, Response};
3use reqwest_middleware::{Middleware, Next, Result};
4use reqwest_retry::{
5 DefaultRetryableStrategy, RetryPolicy, RetryTransientMiddleware, RetryableStrategy,
6};
7
8#[derive(Debug, Clone)]
13pub struct FWOptions {
14 pub skip_retry: bool,
16 pub no_auth: bool,
18}
19
20pub struct FWRetryTransientMiddleware<
21 T: RetryPolicy + Send + Sync + 'static,
22 R: RetryableStrategy + Send + Sync + 'static = DefaultRetryableStrategy,
23>(Option<RetryTransientMiddleware<T, R>>);
24
25impl<T, R> FWRetryTransientMiddleware<T, R>
26where
27 T: RetryPolicy + Send + Sync + 'static,
28 R: RetryableStrategy + Send + Sync + 'static,
29{
30 pub fn new(retry: Option<RetryTransientMiddleware<T, R>>) -> Self {
33 Self(retry)
34 }
35}
36
37#[async_trait::async_trait]
38impl<T, R> Middleware for FWRetryTransientMiddleware<T, R>
39where
40 T: RetryPolicy + Send + Sync,
41 R: RetryableStrategy + Send + Sync + 'static,
42{
43 async fn handle(
44 &self,
45 mut req: Request,
46 extensions: &mut Extensions,
47 next: Next<'_>,
48 ) -> Result<Response> {
49 let mut skip_retry = req.try_clone().is_none();
51 if let Some(options) = extensions.get::<FWOptions>() {
52 if options.no_auth {
53 req.headers_mut().remove("Authorization");
54 }
55 if options.skip_retry {
56 skip_retry = true;
57 }
58 }
59 if skip_retry {
60 return next.run(req, extensions).await;
61 }
62 match &self.0 {
63 Some(middleware) => middleware.handle(req, extensions, next).await,
64 None => next.run(req, extensions).await,
65 }
66 }
67}