Crate tower_async_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-async.
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.
Note that for these frameworks you do need to use the tower-async-bridge crate to convert
between the tower-async and tower abstractions.
Example server
This example shows how to apply middleware from tower-http to a Service and then run
that service using hyper.
use tower_async_http::{
add_extension::AddExtensionLayer,
compression::CompressionLayer,
propagate_header::PropagateHeaderLayer,
sensitive_headers::SetSensitiveRequestHeadersLayer,
set_header::SetResponseHeaderLayer,
validate_request::ValidateRequestHeaderLayer,
};
use tower_async_bridge::ClassicServiceExt;
use tower_async::{ServiceBuilder, service_fn};
use tower::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)))
// 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(ValidateRequestHeaderLayer::bearer("passwordlol"))
// Accept only application/json, application/* and */* in a request's ACCEPT header
.layer(ValidateRequestHeaderLayer::accept("application/json"))
// Wrap a `Service` in our middleware stack
.service_fn(handler);
// Turn the service into a shared classic one,
// so that it can be reused in a `hyper` server.
let service = Shared::new(service.into_classic());
// And run our service using `hyper`
let addr = SocketAddr::from(([127, 0, 0, 1], 3000));
Server::bind(&addr)
.serve(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_async_http::{
decompression::DecompressionLayer,
set_header::SetRequestHeaderLayer,
};
use tower_async_bridge::AsyncServiceExt;
use tower_async::{ServiceBuilder, Service, ServiceExt};
use hyper::Body;
use http::{Request, HeaderValue, header::USER_AGENT};
#[tokio::main]
async fn main() {
let mut client = ServiceBuilder::new()
// 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_async::Service`.
.service(hyper::Client::new().into_async());
// Make a request
let request = Request::builder()
.uri("http://example.com")
.body(Body::empty())
.unwrap();
let response = client
.call(request)
.await
.unwrap();
}Feature Flags
All middleware are disabled by default and can be enabled using cargo features.
For example, to enable the Timeout middleware, add the “timeout” feature flag in
your Cargo.toml:
tower-async-http = { version = "0.1", features = ["timeout"] }
You can use "full" to enable everything:
tower-async-http = { version = "0.1", features = ["full"] }
Modules
- add_extension
add-extensionMiddleware that clones a value into each request’s extensions. - auth
authAuthorization related middleware. - catch_panic
catch-panicConvert panics into responses. - Tools for classifying responses as either success or failure.
- compression
compression-brorcompression-deflateorcompression-gziporcompression-zstdMiddleware that compresses response bodies. - cors
corsMiddleware which adds headers for CORS. - decompression
decompression-brordecompression-deflateordecompression-gzipordecompression-zstdMiddleware that decompresses request and response bodies. - follow_redirect
follow-redirectMiddleware for following redirections. - limit
limitMiddleware for limiting request bodies. - map_request_body
map-request-bodyApply a transformation to the request body. - map_response_body
map-response-bodyApply a transformation to the response body. - normalize_path
normalize-pathMiddleware that normalizes paths. - propagate_header
propagate-headerPropagate a header from the request to the response. - request_id
request-idSet and propagate request ids. - sensitive_headers
sensitive-headersMiddlewares that mark headers as sensitive. - set_header
set-headerMiddleware for setting headers on requests and responses. - set_status
set-statusMiddleware to override status codes. - timeout
timeoutMiddleware that applies a timeout to requests. - trace
trace - validate_request
validate-requestMiddleware that validates requests.
Enums
- CompressionLevel
compression-brorcompression-deflateorcompression-gziporcompression-zstdordecompression-brordecompression-deflateordecompression-gzipordecompression-zstdLevel of compression data should be compressed with. - The latency unit used to report latencies by middleware.
Traits
- Extension trait that adds methods to
tower_async::ServiceBuilderfor adding middleware from tower-http.
Type Definitions
- Alias for a type-erased error type.