# tower-http-client
[](https://github.com/alekseysidorov/tower-http-client/actions/workflows/ci.yml)
[](https://crates.io/crates/tower-http-client)
[](https://docs.rs/tower-http-client)
[](./LICENSE)
This library provides middlewares and various utilities for HTTP-clients.
Thus, it extends the [`tower_http`] functionality for creating HTTP clients
using [`tower`] middlewares.
At the moment, the de facto standard client library is [`reqwest`], which is
poorly compatible with the [`tower`] services, but thanks to the
[`tower_reqwest`] crate, it can be used with the any [`tower_http`] layers.
The first goal of the project is to create a more flexible and extensible
alternative for [`reqwest_middleware`].
## Examples
Simple client usage with layers from the [`tower_http`].
```rust
use http::{header::USER_AGENT, HeaderValue};
use tower::{ServiceBuilder, ServiceExt};
use tower_http::ServiceBuilderExt;
use tower_http_client::{ServiceExt as _, ResponseExt as _};
use tower_reqwest::HttpClientLayer;
use wiremock::{Mock, MockServer, ResponseTemplate, matchers::{method, path}};
/// Implementation agnostic HTTP client.
type HttpClient = tower::util::BoxCloneService<
http::Request<reqwest::Body>,
http::Response<reqwest::Body>,
anyhow::Error,
>;
/// Creates HTTP client with Tower layers on top of the given client.
fn make_client(client: reqwest::Client) -> HttpClient {
ServiceBuilder::new()
// Add some layers.
.override_request_header(USER_AGENT, HeaderValue::from_static("tower-http-client"))
// Make client compatible with the `tower-http` layers.
.layer(HttpClientLayer)
.service(client)
.map_err(anyhow::Error::from)
.boxed_clone()
}
#[tokio::main]
async fn main() -> anyhow::Result<()> {
// Start a mock server for testing
let mock_server = MockServer::start().await;
// Configure mock response
Mock::given(method("GET"))
.and(path("/hello"))
.respond_with(ResponseTemplate::new(200).set_body_string("Hello, World!"))
.mount(&mock_server)
.await;
// Create a new client.
let mut client = make_client(reqwest::Client::new());
// Execute request by using this service.
let response = client
.get(format!("{}/hello", mock_server.uri()))
.send()
.await?;
let text = response.body_reader().utf8().await?;
println!("{text}");
Ok(())
}
```
[`tower_reqwest`]: https://docs.rs/tower-reqwest
[`reqwest_middleware`]: https://docs.rs/reqwest-middleware
[`reqwest`]: https://github.com/seanmonstar/reqwest
[`tower_http`]: https://github.com/tower-rs/tower-http
[`tower`]: https://github.com/tower-rs/tower