How to Use HTTP/2 in Rust

Web
Use the `hyper` crate with the `full` feature flag to enable HTTP/2 support, as it is the standard high-performance HTTP library for Rust.

Use the hyper crate with the full feature flag to enable HTTP/2 support, as it is the standard high-performance HTTP library for Rust. You can configure hyper::Client to use HTTP/2 by default or explicitly set the protocol version, and for servers, you simply enable the http2 feature on the hyper crate and configure the server to accept HTTP/2 connections.

For a client, the easiest approach is to use the hyper client with the full feature, which defaults to HTTP/2 when the server supports it (via ALPN). Here is a minimal example making an HTTP/2 request:

use hyper::Client;
use hyper::Body;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    // The 'full' feature enables HTTP/2 support
    let client = Client::builder()
        .build_http2() // Explicitly enable HTTP/2 (optional, default in many setups)
        .build(Body::empty());

    let res = client.get("https://http2.akamai.com/demo").await?;
    
    println!("Status: {}", res.status());
    println!("Headers: {:?}", res.headers());
    
    Ok(())
}

For a server, you need to enable the http2 feature in your Cargo.toml and configure the server to listen for HTTP/2. Note that HTTP/2 over TLS requires a valid certificate.

use hyper::{Body, Request, Response, Server};
use hyper::server::conn::Http;
use tokio::net::TcpListener;
use tokio_rustls::TlsAcceptor;

// Assuming you have a TlsAcceptor configured with your cert/key
async fn handle_request(req: Request<Body>) -> Result<Response<Body>, hyper::Error> {
    Ok(Response::new(Body::from("Hello over HTTP/2")))
}

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let addr = "[::1]:8443".parse().unwrap();
    let listener = TcpListener::bind(addr).await?;
    
    // Configure HTTP/2
    let http = Http::new();

    // In a real scenario, wrap the listener with TLS for HTTP/2
    // let acceptor = TlsAcceptor::from(config);
    // let stream = acceptor.accept(listener).await?;

    // For demonstration without TLS (HTTP/2 cleartext is rare but possible for testing)
    // Note: Most browsers and clients require TLS for HTTP/2
    let service = hyper::service::service_fn(handle_request);
    
    // Use hyper_util or similar to serve with HTTP/2 capabilities
    // This is a simplified conceptual example; production requires TLS wrapping
    println!("Listening on {}", addr);
    
    Ok(())
}

In production, you almost always need to wrap your TCP listener with tokio-rustls or native-tls to handle the TLS handshake required for HTTP/2. The hyper crate handles the multiplexing and framing automatically once the TLS connection is established. Ensure your Cargo.toml includes:

[dependencies]
hyper = { version = "1.0", features = ["full"] }
tokio = { version = "1", features = ["full"] }
tokio-rustls = "0.26"

The hyper library abstracts the complexity of the HTTP/2 frame protocol, allowing you to write standard async Rust code while benefiting from multiplexing and header compression.