Crate tower_http
source · [−]Expand description
async fn(HttpRequest) -> Result<HttpResponse, Error>
Overview
tower-http is a library that provides HTTP-specific middleware and utilities built on top of tower.
All middleware uses the http and http-body crates as the HTTP abstractions. That means they’re compatible with any library or framework that also uses those crates, such as hyper, tonic, and warp.
Example server
This example shows how to apply middleware from tower-http to a Service and then run
that service using hyper.
use tower_http::{
add_extension::AddExtensionLayer,
compression::CompressionLayer,
propagate_header::PropagateHeaderLayer,
auth::RequireAuthorizationLayer,
sensitive_headers::SetSensitiveRequestHeadersLayer,
set_header::SetResponseHeaderLayer,
trace::TraceLayer,
};
use tower::{ServiceBuilder, service_fn, make::Shared};
use http::{Request, Response, header::{HeaderName, CONTENT_TYPE, AUTHORIZATION}};
use hyper::{Body, Error, server::Server, service::make_service_fn};
use std::{sync::Arc, net::SocketAddr, convert::Infallible, iter::once};
// Our request handler. This is where we would implement the application logic
// for responding to HTTP requests...
async fn handler(request: Request<Body>) -> Result<Response<Body>, Error> {
// ...
}
// Shared state across all request handlers --- in this case, a pool of database connections.
struct State {
pool: DatabaseConnectionPool,
}
#[tokio::main]
async fn main() {
// Construct the shared state.
let state = State {
pool: DatabaseConnectionPool::new(),
};
// Use tower's `ServiceBuilder` API to build a stack of tower middleware
// wrapping our request handler.
let service = ServiceBuilder::new()
// Mark the `Authorization` request header as sensitive so it doesn't show in logs
.layer(SetSensitiveRequestHeadersLayer::new(once(AUTHORIZATION)))
// High level logging of requests and responses
.layer(TraceLayer::new_for_http())
// Share an `Arc<State>` with all requests
.layer(AddExtensionLayer::new(Arc::new(state)))
// Compress responses
.layer(CompressionLayer::new())
// Propagate `X-Request-Id`s from requests to responses
.layer(PropagateHeaderLayer::new(HeaderName::from_static("x-request-id")))
// If the response has a known size set the `Content-Length` header
.layer(SetResponseHeaderLayer::overriding(CONTENT_TYPE, content_length_from_response))
// Authorize requests using a token
.layer(RequireAuthorizationLayer::bearer("passwordlol"))
// Wrap a `Service` in our middleware stack
.service_fn(handler);
// And run our service using `hyper`
let addr = SocketAddr::from(([127, 0, 0, 1], 3000));
Server::bind(&addr)
.serve(Shared::new(service))
.await
.expect("server error");
}Keep in mind that while this example uses hyper, tower-http supports any HTTP client/server implementation that uses the http and http-body crates.
Example client
tower-http middleware can also be applied to HTTP clients:
use tower_http::{
decompression::DecompressionLayer,
set_header::SetRequestHeaderLayer,
trace::TraceLayer,
classify::StatusInRangeAsFailures,
};
use tower::{ServiceBuilder, Service, ServiceExt};
use hyper::Body;
use http::{Request, HeaderValue, header::USER_AGENT};
#[tokio::main]
async fn main() {
let mut client = ServiceBuilder::new()
// Add tracing and consider server errors and client
// errors as failures.
.layer(TraceLayer::new(
StatusInRangeAsFailures::new(400..=599).into_make_classifier()
))
// Set a `User-Agent` header on all requests.
.layer(SetRequestHeaderLayer::overriding(
USER_AGENT,
HeaderValue::from_static("tower-http demo")
))
// Decompress response bodies
.layer(DecompressionLayer::new())
// Wrap a `hyper::Client` in our middleware stack.
// This is possible because `hyper::Client` implements
// `tower::Service`.
.service(hyper::Client::new());
// Make a request
let request = Request::builder()
.uri("http://example.com")
.body(Body::empty())
.unwrap();
let response = client
.ready()
.await
.unwrap()
.call(request)
.await
.unwrap();
}Feature Flags
All middleware are disabled by default and can be enabled using cargo features.
For example, to enable the Trace middleware, add the “trace” feature flag in
your Cargo.toml:
tower-http = { version = "0.1", features = ["trace"] }You can use "full" to enable everything:
tower-http = { version = "0.1", features = ["full"] }Getting Help
If you’re new to tower its guides might help. In the tower-http repo we also have a number
of examples showing how to put everything together. You’re also welcome to ask in
the #tower Discord channel or open an issue with your question.
Modules
add-extensionMiddleware that clones a value into each request’s extensions.
authAuthorization related middleware.
catch-panicConvert panics into responses.
Tools for classifying responses as either success or failure.
compression-br or compression-deflate or compression-gzipMiddleware that compresses response bodies.
decompression-br or decompression-deflate or decompression-gzipMiddleware that decompresses response bodies.
follow-redirectMiddleware for following redirections.
limitMiddleware for limiting request bodies.
map-request-bodyApply a transformation to the request body.
map-response-bodyApply a transformation to the response body.
metricsMiddlewares for adding metrics to services.
propagate-headerPropagate a header from the request to the response.
request-idSet and propagate request ids.
sensitive-headersMiddlewares that mark headers as sensitive.
set-headerMiddleware for setting headers on requests and responses.
set-statusMiddleware to override status codes.
timeoutMiddleware that applies a timeout to requests.
Enums
The latency unit used to report latencies by middleware.
Traits
Extension trait that adds methods to tower::ServiceBuilder for adding middleware from
tower-http.
Type Definitions
Alias for a type-erased error type.