reqwest_chain/chainable.rs
1use reqwest_middleware::reqwest::{Request, Response};
2use reqwest_middleware::Error;
3
4/// Describes:
5///
6/// - which request outcomes should be retried
7/// - how the request should be updated to retry
8#[async_trait::async_trait]
9pub trait Chainer {
10 type State: Sync + Send + Default;
11
12 /// Inspect the result of the previous request, to decide whether to make
13 /// another request.
14 ///
15 /// - If another request is required, update the previous request to form the
16 /// next request in the chain, and return `Ok(None)`.
17 /// - If the response is ready, return it inside `Ok(Some(response))`.
18 /// - If an error occurs and you cannot continue, return `Err(error)`.
19 ///
20 /// Returning a response, or an error, will result in termination of the chain.
21 ///
22 /// Information is available from:
23 ///
24 /// - self (global state, instantiated at middleware creation)
25 /// - result (the result of the previous request)
26 /// - state (local state, instantiated for each request chain)
27 ///
28 /// Global side effects can be managed via interior mutability of `self`.
29 async fn chain(
30 &self,
31 result: Result<Response, Error>,
32 state: &mut Self::State,
33 request: &mut Request,
34 ) -> Result<Option<Response>, Error>;
35
36 /// Safety valve to protect against infinite chaining.
37 ///
38 /// This value may be overriden by the user.
39 fn max_chain_length(&self) -> u32 {
40 /// We limit the number of retries to avoid stack-overflow issues due to the recursion.
41 ///
42 /// This can be increased by the user.
43 const DEFAULT_MAXIMUM_CHAIN_LENGTH: u32 = 7;
44 DEFAULT_MAXIMUM_CHAIN_LENGTH
45 }
46}
47
48pub struct ChainMiddleware<T> {
49 inner: T,
50}
51
52impl<T> ChainMiddleware<T> {
53 pub fn new(inner: T) -> Self {
54 Self { inner }
55 }
56
57 pub(crate) fn inner(&self) -> &T {
58 &self.inner
59 }
60}