Skip to main content

Crate tower_http

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 and hyper-util.

use tower_http::{
    compression::CompressionLayer,
    trace::TraceLayer,
};
use tower::{ServiceBuilder, service_fn, BoxError};
use http::{Request, Response};
use std::net::{SocketAddr, Ipv6Addr};
use bytes::Bytes;
use http_body_util::Full;
use hyper_util::rt::{TokioIo, TokioExecutor};
use hyper_util::service::TowerToHyperService;


#[tokio::main]
async fn main() -> Result<(), BoxError> {
    let addr = SocketAddr::from((Ipv6Addr::LOCALHOST, 8000));
    let listener = tokio::net::TcpListener::bind(addr).await?;
    println!("Listening on http://{}", addr);

    loop {
        let (socket, _) = listener.accept().await?;

        tokio::spawn(async move {
            let socket = TokioIo::new(socket);

            // Build our middleware stack
            let service = ServiceBuilder::new()
                .layer(TraceLayer::new_for_http())
                .layer(CompressionLayer::new())
                .service_fn(handler);

            // Wrap it for hyper
            let hyper_service = TowerToHyperService::new(service);

            if let Err(err) = hyper_util::server::conn::auto::Builder::new(TokioExecutor::new())
                .serve_connection(socket, hyper_service)
                .await
            {
                eprintln!("failed to serve connection: {err:#}");
            }
        });
    }
}

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_util::{rt::TokioExecutor, client::legacy::Client};
use http_body_util::Full;
use bytes::Bytes;
use http::{Request, HeaderValue, header::USER_AGENT};

#[tokio::main]
async fn main() {
let client = Client::builder(TokioExecutor::new()).build_http();
    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 `Client` in our middleware stack.
        // This is possible because `Client` implements
        // `tower::Service`.
        .service(client);

    // Make a request
    let request = Request::builder()
        .uri("http://example.com")
        .body(Full::<Bytes>::default())
        .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§

classify
Tools for classifying responses as either success or failure.
follow_redirect
Middleware for following redirections.
services
Services that return responses without wrapping other Services.

Enums§

LatencyUnit
The latency unit used to report latencies by middleware.

Type Aliases§

BoxError
Alias for a type-erased error type.