hyperium/h2: A Rust HTTP/2 Protocol Engine
HTTP 2.0 client & server implementation for Rust.
At a glance
- What is it?
- The h2 crate implements HTTP/2 client and server behavior for asynchronous Rust applications built on Tokio. It deliberately leaves TCP management, TLS, and HTTP/1.x upgrades to a surrounding networking stack.
- Who is it for?
- Adopt h2 when an application already supplies an asynchronous byte stream and needs direct access to the HTTP/2 client or server implementation. Do not choose it as a complete web server or network bootstrap layer because connection establishment, TLS, and HTTP/1.x upgrades are outside its scope.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 13 days ago.
- What is it written in?
- Mainly Rust, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.
Editorial analysis
h2 Targets the HTTP/2 Protocol Boundary
h2 solves a narrow but consequential problem in Rust networking: implementing the HTTP/2 client and server state machines over an asynchronous byte transport. It is intended for developers building network services or clients on Tokio who need HTTP/2 behavior but do not want to implement framing, stream coordination, headers, flow control, and related protocol mechanics themselves. The crate supports both sides of the connection and describes itself as implementing the full HTTP/2 specification.
The package is not a general-purpose web framework. According to the README, h2 does not manage TCP connections, perform an HTTP 1.0 upgrade, configure TLS, or implement features outside the HTTP/2 specification. The surrounding application must therefore establish and secure the transport before handing it to h2. This boundary is useful for libraries and frameworks because it keeps transport policy separate from HTTP/2 processing.
The README identifies hyper as the project now using h2 and as the layer that supplies the omitted networking features. That relationship defines h2's role more clearly than a generic comparison with HTTP server frameworks would: h2 is the HTTP/2 engine, while hyper assembles broader client and server capabilities around it. This split is also why adding `h2` alone does not produce an application that can accept arbitrary internet traffic.
Tokio Transport and HTTP/2 State Management
The package is built on Tokio and depends on `tokio` with its `io-util` feature, along with `tokio-util` codec and I/O features. The repository contains separate client and server examples, protocol-focused fixtures, fuzzing code, benchmarks, and integration test workspaces. Based on that repository layout, h2 is developed as a library with distinct client, server, and protocol-validation concerns rather than as a standalone executable.
An h2 application supplies an asynchronous transport, and h2 manages HTTP/2 behavior over that transport. Its client and server modules expose the roles needed to process HTTP/2 exchanges. Internal responsibilities associated with an HTTP/2 implementation include coordinating requests or responses as streams, encoding HTTP headers, applying flow control, and moving data over the connection. The README states that the implementation covers the full HTTP/2 specification and passes `h2spec`, but it does not provide a simplified data-flow diagram or a short conceptual protocol example.
The crate also uses the `http` crate, `bytes`, `tracing`, `futures-core`, and `futures-sink`. The optional `stream` feature enables `futures::Stream` implementations for various types. A separate `unstable` feature exposes APIs without backward-compatibility guarantees, and Cargo.toml explicitly limits that feature to experimentation. This is an important API boundary for dependency selection: consumers who need stable interfaces should stay with the default public surface rather than adopting the crate through `unstable`.
The absence of transport management affects both roles equally. A server still needs something that accepts connections and supplies a Tokio-compatible I/O object. A client still needs a resolver, connector, and any TLS layer it requires. h2 starts at the HTTP/2 boundary, so a missing socket or certificate setting cannot be solved by changing an h2 flag.
Adding h2 and Importing the Server API
The README documents `h2` as a Cargo dependency in the `0.4` release line. Add the entry to Cargo.toml:
[dependencies]
h2 = "0.4"With that entry present, Cargo can resolve and fetch the crate. The repository identifies the current package version as `0.4.20` in Cargo.toml, while the README uses the broader `0.4` requirement. The package uses Rust edition 2021 and declares `rust-version = "1.63"` as its minimum supported Rust version. A project using an older compiler cannot rely on the current package metadata for compilation.
The README then demonstrates importing the server connection type:
extern crate h2;
use h2::server::Connection;
fn main() {
// ...
}This is a compile-level starting point, not a complete server. The README does not document the required async runtime setup, transport implementation, listener configuration, or connection-driving code. The repository includes `examples/client.rs` and `examples/server.rs`; those examples are the more appropriate starting points when a reader needs a working application structure, while `https://docs.rs/h2` provides the crate reference.
A first implementation should keep responsibilities separate. Create and accept the connection outside h2, apply TLS where the deployment requires it, and pass the resulting asynchronous I/O resource into the relevant client or server API. The documentation does not establish that a separate crate such as hyper is mandatory for every h2 user, because lower-level applications can provide compatible transport code themselves. It does establish that TCP management and TLS are responsibilities h2 declines to handle.
Selecting Features Without Breaking Public API Stability
Cargo.toml defines two named features, and they serve different purposes. The `stream` feature enables `futures::Stream` implementations for various h2 types. This is a defined capability rather than an explicitly unstable interface, although downstream compatibility still depends on the crate release and Rust ecosystem versions selected by the application.
The `unstable` feature has a much clearer warning. Any API exposed through it has no backward-compatibility guarantee, and Cargo.toml says it should be used only for experimentation. It must not be used in another published crate. This creates a specific upgrade cost: code depending on `unstable` can require source changes even when the package remains within its `0.4` version line. The warning is not limited to code used only by tests or examples, because the restriction is on publishing a crate that depends on this feature.
Feature choices should therefore be recorded as deliberate API decisions. Enabling `stream` changes which trait implementations consumers can use. Enabling `unstable` broadens access to interfaces whose compatibility the package author explicitly declines to guarantee. The README does not document the full feature matrix or a formal deprecation schedule, so Cargo.toml and the crate reference are the relevant sources when checking exactly what a release exposes.
The minimum Rust version adds another constraint to upgrades. A dependency update can remain within h2's `0.4` line while still requiring a newer compiler than an application permits. Before accepting such an update, compare `rust-version` in Cargo.toml with the Rust toolchain used by continuous integration and release builds.
Release History and License Boundaries
The repository is not archived, and its last push was on 2026-10-09. Recent releases include v0.4.18 on 2026-08-20, v0.4.19 on 2026-08-24, and v0.4.20 on 2026-10-06. Those dates document recent repository and release activity. They do not establish that every part of the public API remains stable, particularly because the `unstable` feature has separate guarantees from the default surface.
The repository includes CHANGELOG.md, which is the first file to inspect when evaluating an upgrade or selecting a release. Cargo.toml also states that releasing to crates.io requires updating CHANGELOG.md and creating a Git tag. The README does not publish a release schedule, support window, or separate migration guide, so consumers cannot infer a maintenance promise from the release list alone.
The crate uses the MIT license. The LICENSE file governs use, modification, distribution, and sublicensing under its terms, including the required preservation of copyright and license notices. A downstream project may also need to account for the licenses of its dependencies, but this review does not infer terms that are not stated in those projects' own license files.
There is no homepage listed for the repository. Its canonical project links in the README point to the GitHub repository, crates.io, docs.rs, Tokio, hyper, and h2spec. This distinction matters when seeking release instructions or examples: use the repository and docs.rs rather than assuming a separate project website exists.
Where h2 Differs from hyper
The clearest failure mode is selecting h2 without a compatible asynchronous transport. Since the crate does not manage TCP connections or TLS, a minimal Cargo installation is not a deployable server. The application must decide how to listen, accept connections, negotiate TLS when required, and provide Tokio-compatible I/O. Without those layers, the README's `h2::server::Connection` import has no executable networking setup around it.
h2 is also the wrong choice when the required behavior is specifically HTTP 1.0 upgrade handling. That exclusion is explicit rather than incidental. Applications seeking web-server features not described by HTTP/2 should not expect this crate to supply them. The README directs users to hyper for connection management, HTTP/1.x upgrades, TLS, and related functionality.
Hyper is a real alternative with a broader design. According to the README, hyper uses h2 and provides the capabilities excluded from the lower-level crate. The practical difference is composition. Hyper handles higher-level networking requirements and relies on h2 for HTTP/2 behavior, while a direct h2 integration places protocol processing inside an application or library that already owns the transport.
This does not make one choice universally better. Direct use of h2 can fit an architecture that needs explicit transport control, while hyper offers a broader abstraction for common client and server work. The documentation does not publish a benchmark comparing their performance, nor does it claim that either approach eliminates all compatibility concerns. The choice should follow the missing layers in the intended application.
Interpreting h2 Correctness and Validation Assets
The README says the implementation passes `h2spec`, and the repository contains `tests/`, `fixtures/`, `fuzz/`, and `benches/`. These entries support the project's emphasis on protocol correctness and show several forms of validation within the repository. The workspace declared in Cargo.toml also includes dedicated test and utility packages such as `tests/h2-fuzz`, `tests/h2-tests`, `tests/h2-support`, `util/genfixture`, and `util/genhuff`.
No benchmark results are documented in the README, so its focus on performance cannot support a quantitative comparison with another Rust HTTP/2 implementation. The presence of a `benches/` directory establishes that benchmarking assets exist, but it does not establish a throughput figure, latency result, memory footprint, or advantage over an alternative.
The `h2spec` statement is also narrower than a claim about every HTTP/2 deployment concern. It concerns conformance with that external test suite, while the API documentation governs how Rust applications configure and consume the crate. Protocol conformance cannot remove the need to pair h2 with a compatible transport, choose appropriate timeouts outside the protocol engine, or verify interoperability with the systems an application will contact.
For an engineering review, these sources answer different questions. `h2spec` concerns protocol behavior, repository tests and fixtures exercise internal and integration cases, examples show intended API usage, and docs.rs describes the current public interface. An application that needs a particular extension, transport pattern, or compatibility guarantee should verify that specific point in the crate reference rather than relying on the general correctness statement.
Editorial conclusion
Adopt h2 when an application already supplies an asynchronous byte stream and needs direct access to the HTTP/2 client or server implementation. Do not choose it as a complete web server or network bootstrap layer because connection establishment, TLS, and HTTP/1.x upgrades are outside its scope. Before adoption, inspect the crate documentation for the exact API matching your transport setup, confirm that Rust 1.63 or later remains compatible with your build environment, and check CHANGELOG.md for changes in the selected release.
Frequently asked questions
Does the h2 Rust crate include TCP and TLS support?
No. The README explicitly excludes TCP connection management and TLS, so the surrounding application must provide the transport before using h2 for HTTP/2.
Can hyperium/h2 be used as both a client and server in Rust?
Yes. The crate provides both client and server HTTP/2 implementations over a compatible asynchronous transport, with APIs in `h2::client` and `h2::server`.
What is the difference between hyperium/h2 and hyper?
The README says hyper uses h2 and supplies capabilities that h2 excludes, including TCP connection management, HTTP 1.0 upgrades, and TLS. h2 focuses on implementing the HTTP/2 specification itself.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/hyperium-h2)Was this useful?