Crates.io | reqwest-chain |
lib.rs | reqwest-chain |
version | |
source | src |
created_at | 2022-12-06 20:23:39.142277 |
updated_at | 2024-12-04 15:25:38.790506 |
description | Apply custom criteria to any reqwest response, deciding when and how to retry. |
homepage | |
repository | https://github.com/tommilligan/reqwest-chain |
max_upload_size | |
id | 731406 |
Cargo.toml error: | TOML parse error at line 18, column 1 | 18 | autolib = false | ^^^^^^^ unknown field `autolib`, expected one of `name`, `version`, `edition`, `authors`, `description`, `readme`, `license`, `repository`, `homepage`, `documentation`, `build`, `resolver`, `links`, `default-run`, `default_dash_run`, `rust-version`, `rust_dash_version`, `rust_version`, `license-file`, `license_dash_file`, `license_file`, `licenseFile`, `license_capital_file`, `forced-target`, `forced_dash_target`, `autobins`, `autotests`, `autoexamples`, `autobenches`, `publish`, `metadata`, `keywords`, `categories`, `exclude`, `include` |
size | 0 |
Apply custom criteria to any reqwest
response, deciding when and how to retry.
reqwest-chain
builds on reqwest-middleware
, to allow you to focus on your core logic without the boilerplate.
This crate is a more general framework than reqwest-retry
. It allows inspection of:
Based on this information, it allows updating any aspect of the next request.
If all you need is a simple retry, you should use reqwest-retry
.
See the tests
directory for several examples.
You should implement Chainer
for your middleware struct. This uses the chain
method to make a decision after each request respones:
Ok(None)
.Ok(Some(response))
.Err(error)
.Below is the initial use case; refresh some authorization credential on request failure.
use reqwest_chain::{Chainer, ChainMiddleware};
use reqwest_middleware::reqwest::{Client, Request, Response, StatusCode};
use reqwest_middleware::reqwest::header::{AUTHORIZATION, HeaderValue};
use reqwest_middleware::{ClientBuilder, ClientWithMiddleware, Error};
// Mimic some external function that returns a valid token.
fn fetch_token() -> String {
"valid-token".to_string()
}
struct FetchTokenMiddleware;
#[async_trait::async_trait]
impl Chainer for FetchTokenMiddleware {
// We don't need it here, but you can choose to keep track of state between
// chained retries.
type State = ();
async fn chain(
&self,
result: Result<Response, Error>,
_state: &mut Self::State,
request: &mut Request,
) -> Result<Option<Response>, Error> {
let response = result?;
if response.status() != StatusCode::UNAUTHORIZED {
return Ok(Some(response))
};
request.headers_mut().insert(
AUTHORIZATION,
HeaderValue::from_str(&format!("Bearer {}", fetch_token())).expect("invalid header value"),
);
Ok(None)
}
}
async fn run() {
let client = ClientBuilder::new(Client::new())
.with(ChainMiddleware::new(FetchTokenMiddleware))
.build();
client
.get("https://example.org")
// If this token is invalid, the request will be automatically retried
// with an updated token.
.header(AUTHORIZATION, "Bearer expired-token")
.send()
.await
.unwrap();
}
Many thanks to the prior work in this area, namely:
reqwest-middleware
for the underlying frameworkreqwest-retry
for inspiration