Repository navigation
HTTP2
Headers: <cwist/app.h>, <cwist/net/http/http2.h>,
<cwist/net/http/http2_flow_control.h>
CWIST implements HTTP/2 itself (HPACK, framing, flow control); it does not use nghttp2 on the server side. Handlers are the same as for HTTP/1.1: requests decoded from HTTP/2 streams go through the normal middleware chain and router.
cwist_app_use_https(app, "cert.pem", "key.pem");
cwist_app_use_https2(app, true); /* h2 over TLS, negotiated with ALPN */or, without TLS:
cwist_app_use_http2(app, true); /* h2c on the plain TCP port */-
h2 (TLS). ALPN offers
h2andhttp/1.1; clients that do not ask forh2keep using HTTP/1.1 on the same port. Enabling h2 also applies an HTTP/2-compatible TLS profile (RFC 7540 cipher requirements, server cipher preference). -
h2c (cleartext). Prior knowledge only: a connection whose first bytes
are the HTTP/2 connection preface is served as HTTP/2, anything else as
HTTP/1.1. The HTTP/1.1
Upgrade: h2chandshake is not implemented. - h2c and HTTPS cannot be enabled on the same port, and h2 requires
cwist_app_use_https(); Multiport checks both.
| Aspect | Value |
|---|---|
| Concurrent streams per connection | 100 (SETTINGS_MAX_CONCURRENT_STREAMS) |
| Initial windows | 1.5 MiB connection, 1 MiB per stream; windows adapt to measured RTT |
| Idle timeout |
CWIST_HTTP2_IDLE_TIMEOUT_MS, default 300 s |
| Shutdown | GOAWAY, then CWIST_HTTP2_GOAWAY_GRACE_MS (default 2 s) before close |
| Rapid-reset defense | token bucket on client RST_STREAM: burst CWIST_HTTP2_MAX_RST_BURST (100), refill CWIST_HTTP2_MAX_RST_RATE (100/s) |
| CONTINUATION flood | orphaned or endless CONTINUATION sequences are rejected (CVE-2024-27983 test in test_http2) |
| Output batching | frames are batched up to CWIST_H2_BATCH_BYTES (default 64 KiB) per flush |
| Deferred responses | completed on the connection thread; other streams keep being served (Async Handlers) |
| Idle TLS connections | parked like HTTP/1.1 ones; on expiry the connection gets GOAWAY |
Conformance: every push to the repository runs h2spec and diffs the result
against a pinned baseline (scripts/ci/h2spec-baseline.txt); new failures fail
the build.
Header fields whose HPACK index cannot be resolved are dropped and counted in
the CWIST_METRIC_H2_HEADERS_DROPPED metric.
int cwist_http2_push_resource(cwist_http_request *req, const char *path, const char *content_type,
const unsigned char *data, size_t data_len);Call from a handler on an HTTP/2 request: CWIST sends PUSH_PROMISE on the
request's stream and the pushed response on a new server stream. The client
must allow push (SETTINGS_ENABLE_PUSH). Returns 0 or -1. Most browsers
no longer accept push.
typedef void (*cwist_http2_request_handler_func)(void *user_ctx, cwist_http_request *req,
cwist_http_response *res);
cwist_error_t cwist_http2_serve_connection(cwist_https_connection *conn, void *user_ctx,
cwist_http2_request_handler_func handler);
cwist_error_t cwist_http2_serve_connection_ex(cwist_https_connection *conn, void *user_ctx,
cwist_http2_request_handler_func handler,
const cwist_http2_stream_hooks *hooks);cwist_http2_serve_connection() reads the client preface, decodes streams,
calls handler per request and writes the responses. It returns when the
connection ends.
cwist_http2_stream_hooks lets a higher layer take over individual streams;
the gRPC server uses it (cwist_grpc_http2_hooks()):
| Hook | Called when |
|---|---|
on_conn_open(user_ctx) / on_conn_close(conn_ctx)
|
the connection starts and ends |
on_headers(conn_ctx, req, stream) |
a request header block completes; return non-NULL to take the stream |
on_data(conn_ctx, stream_ctx, data, len, end_stream) |
a DATA payload arrives for a taken stream (incremental, not buffered) |
on_cancel(conn_ctx, stream_ctx) |
the client sent RST_STREAM |
on_poll(conn_ctx, stream_ctx) |
every dispatcher iteration (enforce deadlines; return nonzero when finished) |
next_deadline_ms(conn_ctx) |
nearest deadline, which bounds the socket wait |
on_close(conn_ctx, stream_ctx) |
the taken stream is torn down |
A taken stream writes its own frames, immediately and from its own thread:
int cwist_http2_stream_send_headers(cwist_h2_stream *stream, int status,
const cwist_http2_header *headers, size_t header_count,
int end_stream);
int cwist_http2_stream_send_data(cwist_h2_stream *stream, const unsigned char *data, size_t len);
int cwist_http2_stream_send_trailers(cwist_h2_stream *stream, const cwist_http2_header *trailers,
size_t trailer_count);send_data splits data to the peer's frame size and window. All three return
0 or -1.
h2_decode_integer(), h2_huffman_decode(), h2_decode_string(),
h2_static_header(), h2_encode_integer() and h2_encode_string() expose the
HPACK primitives (RFC 7541) for tools and tests.
<cwist/net/http/http2_flow_control.h> holds the connection and stream window
accounting used by the server: receive and consume tracking, WINDOW_UPDATE
decisions, send-window reservation, RTT-based network quality estimates and a
pacing allowance. Applications do not need it directly. Handler threads that
send on a gRPC stream with no credit wait for WINDOW_UPDATE instead of failing.
For outgoing requests see HTTP Clients (libcurl-based, with HTTP/2 multiplexing) and gRPC Client (CWIST's own HTTP/2 client).
CWIST wiki, written against the dev branch of c4punks/CWIST. Pages marked "Source:" are generated from files under docs/; fix those in the repository. Questions: Discord.
Getting started
- Installation
- Quick Start
- Linking
- Server Modes
- Configuration and Environment
- Project CLI
- Tutorial / Korean
- Examples and Tutorials
Guides
Core
- API Reference
- Application
- Routing
- Middleware
- Requests and Responses
- Async Handlers
- Streaming Responses
- Error Handling
- Graceful Shutdown
- Multiport
Protocols
- HTTPS and TLS
- HTTP/2
- HTTP/3 and QUIC
- WebTransport
- WebSocket
- Server-Sent Events
- gRPC Server
- gRPC Client
- Protobuf and Codegen
- GraphQL
- WebRTC DataChannels
- HTTP Clients
Web features
- Static Files and Assets
- Big Dumb Reply Cache
- Compression
- Cookies
- Sessions and Flash
- Query Maps
- Multipart Uploads
- HTML Components
- Templates
- JSON
- Validation
- OpenAPI
Security
Data
Runtime
- Memory Management
- Full GC
- Async GC Ownership
- SString
- Reactor and I/O
- Metrics and Health
- Logging
- Testing
Platforms
Performance notes
- Benchmark Methodology
- C1M File Limits
- Reactor Fairness
- Cooperative Queuing
- Classic Pool Starvation
- Reactor Wakeup
- wrk Dual Histogram
- FIXED Endpoint Cache
- ADR-0001
- Durable Queue Gate
- Mux References
Project