h3 Documentation

repository·master·Indexed 21 days ago

https://github.com/hyperium/h3

An asynchronous, runtime-independent HTTP/3 implementation (RFC 9114) that is generic over QUIC transports. It allows users to plug in different QUIC stacks such as Quinn, s2n-quic, or MsQuic. The project includes the core h3 crate, h3-quinn for Quinn integration, h3-webtransport for WebTransport support, and h3-datagram for RFC 9297 implementation.

Tokens
20.5K
Snippets
73
Records
96
Agent score
74%

What's inside h3

  1. Overview of H3 Datagram

    master

    The h3-datagram crate provides an implementation of the RFC 9297 specification designed to work with the h3 crate.

    Warning: This crate is currently in an experimental state. The API is subject to change, may contain bugs, and is not yet considered complete. Use it with caution.

  2. Overview of h3 HTTP/3 implementation

    master

    h3 is an asynchronous HTTP/3 implementation (RFC 9114) that is generic over a provided QUIC transport. This design allows developers to use the HTTP/3 logic while selecting a QUIC implementation that best fits their specific needs.

    Key characteristics:

    • Async-only API: Designed for asynchronous workflows.
    • Runtime Independent: h3 does not spawn its own tasks, making it compatible with any async runtime (e.g., Tokio).
    • Transport Agnostic: Uses traits in the quic module to abstract over QUIC implementations.

    Note: The crate is currently experimental and may contain bugs or undergo API changes.

  3. Use h3-quinn for HTTP/3 over Quinn

    master

    h3-quinn is an integration crate that connects the core h3 HTTP/3 implementation with the quinn QUIC transport library. Use this crate when you need to build a fully functional HTTP/3 client or server using Quinn as your underlying QUIC transport.

    Key capabilities include:

    • Implementation of h3 QUIC transport traits.
    • Full HTTP/3 client and server support.
    • Optional support for QUIC datagrams.
    • Optional tracing support for debugging.
  4. Implement a custom QUIC transport layer

    master

    To use h3 with a custom QUIC implementation, you must implement a trait interface that allows h3 to interact with your transport. h3 does not manage the establishment or acceptance of QUIC connections itself; instead, you create your own Connection object and pass it to server::handshake(conn) or client::handshake(conn).

    To be compatible, your connection must support:

    • Creating unidirectional (send) streams (for control streams, QPACK, and server push).
    • Accepting unidirectional (receive) streams (for remote control/QPACK streams and client push).
    • For clients: Creating bidirectional streams to send requests and receive responses.
    • For servers: Accepting bidirectional streams.
    trait Connection<B: Buf> {
        type SendStream: SendStream<B>;
        type RecvStream: RecvStream;
        type BidiStream: SendStream<B> + RecvStream;
        type Error;
        
        // Accepting streams
        fn poll_accept_bidirectional_stream(self: Pin<&mut Self>, cx: &mut Context)
            -> Poll<Result<Option<Self::BidiStream>, Self::Error>>;
               
        fn poll_accept_recv_stream(self: Pin<&mut Self>, cx: &mut Context)
            -> Poll<Result<Option<Self::RecvStream>, Self::Error>>;
            
        // Creating streams
        fn poll_open_bidirectional_stream(self: Pin<&mut Self>, cx: &mut Context)
            -> Poll<Result<Self::BidiStream, Self::Error>>;
    
        fn poll_open_send_stream(self: Pin<&mut Self>, cx: &mut Context)
            -> Poll<Result<Self::SendStream, Self::Error>>;
    }
  5. How h3 uses QUIC transport abstraction

    master

    The core design of h3 is to decouple the HTTP/3 protocol logic from the underlying QUIC transport. It achieves this through traits defined in the h3::quic module.

    Because h3 is transport-agnostic, you can integrate it with various QUIC implementations. Supported integrations include:

    • Quinn: Via the h3-quinn crate.
    • s2n-quic: Via s2n-quic-h3.
    • MsQuic: Via h3-msquic-async.

    When building an application, you should choose the integration that matches your preferred QUIC stack.

  6. How the h3 architecture and stack work

    master

    The h3 project is designed as a standalone HTTP/3 implementation that is generic over the underlying QUIC transport. This allows users to plug in different QUIC implementations (e.g., kernel-space or user-space) and TLS libraries based on their specific requirements.

    When used within the broader ecosystem, the stack is organized into three layers:

    1. hyper::proto::h3: The integration layer that manages connection lifecycle, runtime integration, and Service/HttpBody usage.
    2. h3: The core crate that implements HTTP/3 data structures and futures. It does not manage connections or spawn tasks itself, making it runtime-agnostic.
    3. QUIC: The underlying transport layer provided by an external library.
  7. Test H3 server in a web browser

    master

    To test the H3 server in a browser like Chromium, you must satisfy two requirements:

    1. The server must listen on IPv6 (--listen=[::]:4433) and use valid certificates (--cert and --key).
    2. The browser must be forced to use QUIC/H3.

    Server command:

    cargo run --example server -- --listen=[::]:4433 --dir=examples/root --cert=examples/cert.der --key=examples/key.der

    Browser command (Chromium):

    chromium --enable-quic --quic-version=h3 --origin-to-force-quic-on=localhost:4433
    cargo run --example server -- --listen=[::]:4433 --dir=examples/root --cert=examples/cert.der --key=examples/key.der
    
    chromium --enable-quic --quic-version=h3 --origin-to-force-quic-on=localhost:4433
  8. Implement an HTTP/3 server with `mod server`

    master

    To implement an HTTP/3 server, you use the server::Connection type. The process involves taking a QUIC endpoint listener and performing a handshake to set up required HTTP/3 streams (control streams, QPACK, etc.).

    Handshake

    You can perform a handshake using the default configuration:

    server::handshake(connection).await

    Or use a builder to customize settings, such as max_field_section_size:

    Connection::builder()
        .max_field_section_size(1024 * 32)
        .handshake(connection)
        .await

    Accepting Requests

    Once the connection is established, you can accept requests using .accept(). This returns an http::Request and a RequestStream.

    // Returns (Request, RequestStream)
    let (req, mut stream) = connection.accept().await?;
    impl<T: quic::Connection<B>, B: Buf> Connection<T, B> {
        pub async fn accept(&mut self)
            -> Result<(Request<()>, RequestStream<T::BidiStream, B>), Error>;
    }
  9. Run the H3 example server

    master

    To start a basic HTTP/3 server using the example implementation, use cargo run with the server example. By default, this will generate a self-signed certificate for encryption. Use the --listen flag to specify the address and port.

    cargo run --example server -- --listen=127.0.0.1:4433
  10. Serve directory content with the H3 server

    master

    You can configure the server to serve files from a specific directory by using the --dir flag. Once the server is running, you can request specific files by appending the filename to the URI in the client.

    # Start server with content directory
    cargo run --example server -- --listen=127.0.0.1:4433 --dir=content/root
    
    # Request a specific file via client
    cargo run --example client -- https://localhost:4433/index.html