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.