blob: c12eeebad8ebcf84871ab4bd5f194c03844f3e48 [file] [log] [blame] [view]
# `oghttp2`: a general purpose HTTP/2 library
## Overview
The code in this directory implements the HTTP/2 internet protocol as specified
in [RFC 9113](https://www.rfc-editor.org/rfc/rfc9113.html).
You will need the following additional pieces of code in order to build a
functioning client or server:
* an event loop, like [`libevent`](https://libevent.org/) or
[`libuv`](https://libuv.org/);
* a TLS library, like [OpenSSL](https://www.openssl.org/); and
* application logic, to generate HTTP headers and bodies for the requests you
want to send, or the responses you want to serve.
### Motivation
Back in 2018, the open source [Envoy proxy](https://github.com/envoyproxy/envoy)
community [discovered](https://github.com/envoyproxy/envoy/issues/5155) that the
[`http-parser`](https://github.com/nodejs/http-parser) HTTP/1.1 codec library in
use at the time was no longer actively maintained. While working to resolve this
issue, Google engineers evaluated several HTTP/1 codec libraries as potential
replacements. After much consideration, we decided to release the Google HTTP/1
codec library (Balsa) as part of the [QUICHE](https://github.com/google/quiche)
open source project.
At this point, the QUICHE project provided open source implementations of HTTP/1
and HTTP/3, but not HTTP/2. We were motivated in part by this glaring omission,
but also by the desire to provide a modern, readable C++ implementation for use
by Envoy and other future projects.
### History
We reused some existing open source code when building the `oghttp2` library. As
part of the [SPDY](https://www.chromium.org/spdy/spdy-whitepaper/) project,
developers on the Chromium project worked with other Google engineers to invent
a new multiplexed transport for HTTP. As the project evolved over time, those
engineers built several shared utilities, many of which survive to the present
day.
These utilities are incorporated wholesale into `oghttp2`:
* a wire format encoder, in `http2/core/spdy_framer.h`;
* a wire format decoder, in `http2/decoder/http2_frame_decoder.h`;
* a HPACK encoder, in `http2/hpack/hpack_encoder.h`; and
* a HPACK decoder, in `http2/hpack/hpack_decoder_adapter.h`.
The name of the library is related to this history: it was built from the
"original generation" HTTP/2 implementation.
Given that part of our motivation for the `oghttp2` project was the needs of the
Envoy open source project, the first piece that we built was a C++ API around
the existing HTTP/2 library that Envoy used at that time:
[`nghttp2`](https://nghttp2.org/). This API started as an "adapter" layer
between Envoy's notion of a codec and what the `nghttp2` library provided, which
is why `oghttp2` is located in `http2/adapter`.
We would like to thank the `nghttp2` project for providing a straightforward C
API that we could build on.
## Code Overview
The main structure of the library consists of two components:
* a session object that represents a single multiplexed HTTP/2 connection
(called a `Http2Adapter` in the code), and
* a visitor interface (`Http2VisitorInterface`) that application code can
implement in order to receive HTTP/2 events.
An application can take certain actions to update the state of the HTTP/2
connection by invoking `Http2Adapter` methods. The application can observe the
effects of those actions and the behavior of the peer as `Http2VisitorInterface`
callbacks are invoked.
Consider the following example:
```
Http2Adapter* client_session = /* code to initialize the session */;
MyStreamStruct* stream_data = new MyStreamStruct;
const int32_t stream_id =
client_session->SubmitRequest({{":authority", "www.example.com"},
{":scheme", "http"},
{":method", "GET"},
{":path", "/index.html"}},
/*end_stream=*/true,
/*user_data=*/stream_data);
const int status = client_session->Send();
// Handle error if status is nonzero.
```
This is how a client would send a request on a new stream. When the request is
actually sent, the client application would receive an `OnFrameSent()` callback
with the `HEADERS` frame type, the stream ID on which the request was sent, the
payload size, and any flags set on the frame.
### Common Types
Several protocol elements from the spec are defined as types in
`http2_protocol.h`:
* `Http2StreamId`: the 31-bit stream ID
* `FrameType`: the 8-bit frame type value (e.g. `HEADERS`, `DATA`, etc.)
* `FrameFlags`: each of the frame flag values defined in the specification
* `Http2ErrorCode`: an enumeration of the error codes
* `Http2KnownSettingsId`: an enumeration of the `SETTINGS` identifiers
This file also provides several useful constants related to limits or initial
values defined in the specification.
### Design
### Adapter Implementations