3 unstable releases

0.2.1 Jan 3, 2025
0.2.0 Jan 3, 2025
0.1.0 Dec 30, 2024

#698 in HTTP server

Download history 93/week @ 2024-12-25 253/week @ 2025-01-01

346 downloads per month

MIT license

18KB
246 lines

tower-server

Server utility for running hyper HTTP servers with tower-service.

Integrates with rustls and implements graceful shutdown using tokio_util/CancellationToken.


lib.rs:

High-level hyper server interfacing with tower-service.

Features:

  • rustls integration
  • Graceful shutdown using CancellationToken
  • Optional connnection middleware
  • Optional TLS connection middleware, for example for mTLS integration

Example usage using Axum:

let server = tower_server::Builder::new("0.0.0.0:8080".parse().unwrap())
    // graceful shutdown setup:
    .with_cancellation_token(Default::default())
    .bind()
    .await
    .unwrap();

server.serve(axum::Router::new()).await;

Example using connection middleware

#[derive(Clone)]
struct RemoteAddr(std::net::SocketAddr);

let server = tower_server::Builder::new("0.0.0.0:8080".parse().unwrap())
    .with_connection_middleware(|req, remote_addr| {
        req.extensions_mut().insert(RemoteAddr(remote_addr));
    })
    .bind()
    .await
    .unwrap();

server.serve(axum::Router::new()).await;

Example using TLS connection middleware

use rustls_pki_types::CertificateDer;
use hyper::body::Incoming;

#[derive(Clone)]
struct PeerCertMiddleware;

/// A request extension that includes the mTLS peer certificate
#[derive(Clone)]
struct PeerCertificate(CertificateDer<'static>);

impl tower_server::tls::TlsConnectionMiddleware for PeerCertMiddleware {
    type Data = Option<PeerCertificate>;

    /// Step 1: Extract data from the rustls server connection.
    /// At this stage of TLS handshake the http::Request doesn't yet exist.
    fn data(&self, connection: &rustls::ServerConnection) -> Self::Data {
        Some(PeerCertificate(connection.peer_certificates()?.first()?.clone()))
    }

    /// Step 2: The http::Request now exists, and the request extension can be injected.
    fn call(&self, req: &mut http::Request<Incoming>, data: &Option<PeerCertificate>) {
        if let Some(peer_certificate) = data {
            req.extensions_mut().insert(peer_certificate.clone());
        }
    }
}

#[derive(Clone)]
struct RemoteAddr(std::net::SocketAddr);

let server = tower_server::Builder::new("0.0.0.0:8080".parse().unwrap())
    .with_tls_connection_middleware(PeerCertMiddleware)
    .bind()
    .await
    .unwrap();

server.serve(axum::Router::new()).await;

Dependencies

~14–24MB
~445K SLoC