HTTP Connection Manager Deep-Dive
What This Component Does
The HTTP Connection Manager (HCM) is Envoy’s most critical network filter. It bridges the gap between raw TCP bytes (downstream connections) and HTTP-level request/response processing. The HCM manages HTTP codec instantiation (HTTP/1.1, HTTP/2, HTTP/3), creates per-request streams, drives the HTTP filter chain, handles route configuration (from RDS or inline), manages access logging, integrates distributed tracing, and coordinates timeouts/idle management.
Every HTTP request processed by Envoy passes through the HCM. It is configured as a network filter (type envoy.filters.network.http_connection_manager) in listener filter chains and is the terminal filter for most HTTP-serving listeners.
Use cases: Any listener handling HTTP traffic uses the HCM. It is the core component for API gateways, service mesh sidecars, gRPC proxying, and HTTP reverse proxies. The HCM is always enabled for HTTP listeners; you configure it via the HttpConnectionManager protobuf message in bootstrap or LDS.
How It Works
The HCM receives raw bytes from the network filter chain via the onData() callback, feeds them into an HTTP codec, and dispatches decoded requests through a configurable chain of HTTP filters (authentication, rate limiting, routing, etc.). Each HTTP request creates an ActiveStream that tracks its lifecycle from headers to trailers.
Internal Flow Diagram
flowchart TD
A[Network::ReadFilter::onData()<br/>Raw bytes from downstream] --> B[HTTP Codec<br/>HTTP/1.1: http-parser<br/>HTTP/2: nghttp2<br/>HTTP/3: quiche]
B --> C[onMessageBegin / onHeaders<br/>Create ActiveStream]
C --> D[ActiveStream::decodeHeaders()<br/>Traverse HTTP filter chain]
D --> E{Filter returns?}
E -->|Continue| F[Next filter in chain]
E -->|StopIteration| G[Pause chain<br/>Await continueDecoding()]
F --> H[Router Filter<br/>Terminal filter]
H --> I[Route Table Match<br/>RDS or inline routes]
I --> J[Select cluster + upstream<br/>Via ClusterManager]
J --> K[Upstream request<br/>Connection pool]
K --> L[Upstream response]
L --> M[ActiveStream::encodeHeaders()<br/>Reverse filter chain]
M --> N[HTTP Codec encode<br/>Serialize response]
N --> O[Write to downstream<br/>connection]
O --> P[Access Log<br/>After response complete]
style A fill:#f9f
style P fill:#9f9
Step-by-Step Process:
-
Codec Selection: During HCM creation, the codec type is determined from config (
AUTO_DETECT,HTTP1,HTTP2,HTTP3).AUTO_DETECTreads the initial bytes and ALPN to select. The codec is created insource/common/http/conn_manager_impl.ccviacreateCodec(). -
Stream Creation: When the codec parses request headers, it calls
newStream()on the HCM, which creates anActiveStream. TheActiveStreamis the central object for a single request lifecycle—it holds references to the filter chain, route, request/response headers, and watermark state. -
Filter Chain Execution (Decode Path):
ActiveStream::decodeHeaders()iterates through HTTP filters in order (configured inhttp_filtersfield). Each filter receives headers, data, and trailers callbacks. Filters can:Continue: Pass to the next filter.StopIteration: Pause (e.g., waiting for external auth). CallcontinueDecoding()to resume.StopAllIterationAndBuffer: Buffer all data until resumed.- Directly send a local reply (e.g., 403 from auth filter) via
sendLocalReply().
-
Route Resolution: Typically happens in the router filter or earlier (some filters access the route for config). Route tables are loaded from RDS or inline config. Route matching checks domains, paths, headers, and query parameters against
RouteEntryobjects insource/common/router/config_impl.cc. -
Upstream Dispatch: The Router filter (terminal filter) in
source/common/router/router.ccselects the upstream cluster, picks a host via load balancer, acquires a connection from the pool, and forwards the request. It handles retries, timeouts, and hedging. -
Encode Path: Upstream response flows back through
encodeHeaders()/encodeData()/encodeTrailers()in reverse filter order. Filters can modify response headers (e.g., add CORS headers, strip internal headers). -
Access Logging: After the response completes (or on stream reset), the HCM invokes all configured access loggers (
source/common/http/conn_manager_impl.cc:doDeferredStreamDestroy()). Log formats support command operators (%REQ()%,%RESP()%,%DURATION%, etc.). -
Idle/Timeout Management: The HCM tracks idle timeouts (close connection after inactivity), stream timeouts (per-request deadline), and drain timeouts (graceful shutdown). These are managed via libevent timers on the worker’s dispatcher.
Design Patterns & Trade-offs:
- Per-stream filter instances: Each stream gets its own filter chain instances, providing isolation but costing allocations. Mitigated by arena/pool allocators for common filter types.
- Codec abstraction: A single
ServerConnectioninterface hides HTTP/1.1 vs HTTP/2 vs HTTP/3 differences. Trade-off: some protocol-specific behaviors leak through (e.g., HTTP/2 flow control, HTTP/1.1 connection-level vs stream-level). - Watermark-based backpressure: High watermark on downstream buffers triggers
StopIterationupstream, preventing memory blowup on slow clients. Complex but necessary for production stability. - Route config caching: Route tables from RDS are shared (read-only) across all streams via
shared_ptr. Updates are atomic (swap pointer via TLS).
Key Code Paths
Core HCM Implementation
source/common/http/conn_manager_impl.h-ConnectionManagerImplclass definition withActiveStreaminner class.source/common/http/conn_manager_impl.cc- Core logic:onData()(~L200),newStream()(~L400),ActiveStream::decodeHeaders()(~L600),encodeHeaders()(~L900), access log dispatch.
HCM Extension Filter Factory
source/extensions/filters/network/http_connection_manager/config.cc-HttpConnectionManagerFilterConfigFactorycreatesConnectionManagerImplfrom protobuf config. Parseshttp_filters, route config, codec options.source/extensions/filters/network/http_connection_manager/config.h-HttpConnectionManagerConfigholds parsed config (filters, tracing, access log, timeouts).
HTTP Codecs
source/common/http/http1/codec_impl.cc- HTTP/1.1 codec using http-parser.ServerConnectionImpl::onHeadersComplete()for header parsing.source/common/http/http2/codec_impl.cc- HTTP/2 codec using nghttp2. Handles flow control, GOAWAY, stream resets.source/common/quic/- HTTP/3 (QUIC) codec using quiche.
Filter Chain Management
source/common/http/filter_manager.cc-FilterManageriterates decode/encode filter chains, handlesStopIteration/Continueflow control.
Route Configuration
source/common/router/config_impl.cc-RouteConfigImplparses route tables, implements matching logic.source/common/router/scoped_rds.cc- Scoped RDS for multi-scope route configs.
Configuration
The HCM is configured via the envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager protobuf:
| Field | Type | Default | Effect |
|---|---|---|---|
codec_type | enum | AUTO_DETECT | HTTP protocol: AUTO_DETECT, HTTP1, HTTP2, HTTP3 |
stat_prefix | string | required | Prefix for HCM stats (http.<prefix>.downstream_cx_*) |
route_config | RouteConfiguration | - | Inline route table (mutually exclusive with rds) |
rds | Rds | - | RDS config source for dynamic routes |
http_filters | repeated HttpFilter | required | Ordered filter chain, must end with envoy.filters.http.router |
server_name | string | ”envoy” | Server header value |
stream_idle_timeout | Duration | 5m | Per-stream idle timeout (0 to disable) |
request_timeout | Duration | 0 (disabled) | Total request timeout (headers + body) |
drain_timeout | Duration | 5s | Time to wait for active streams during drain |
access_log | repeated AccessLog | - | Access log sinks (file, gRPC, etc.) |
use_remote_address | bool | false | Trust XFF or use direct downstream IP |
tracing | Tracing | - | Distributed tracing config (Zipkin, Jaeger, OpenTelemetry) |
common_http_protocol_options | HttpProtocolOptions | - | Idle/max connection timeouts |
http2_protocol_options | Http2ProtocolOptions | - | HTTP/2 specific: max concurrent streams, initial window size |
See api/envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.proto for the full protobuf definition.
Extension Points
-
Custom HTTP Filters:
- Implement
Http::StreamDecoderFilterand/orHttp::StreamEncoderFilterinterfaces. - Create a
NamedHttpFilterConfigFactorythat produces filter instances from protobuf config. - Register with
REGISTER_FACTORY(MyFilterFactory). - Add to
http_filterslist in HCM config. - Example: See
source/extensions/filters/http/rbac/for a complete filter implementation.
- Implement
-
Custom Access Loggers:
- Implement
AccessLog::Instanceinterface. - Register factory via
REGISTER_FACTORY. - Add to HCM
access_logconfig. - Built-in: file, gRPC, stderr, OpenTelemetry.
- Implement
-
Custom Route Matching:
- Implement
Router::RouteSpecificFilterConfigfor per-route filter overrides. - Custom matchers via
InputMatcherinterface for header/query matching extensions.
- Implement
-
Wasm Filters:
- Write filters in C++, Rust, Go, or AssemblyScript compiled to Wasm.
- Loaded via
envoy.filters.http.wasmfilter withVmConfig. - See
source/extensions/filters/http/wasm/.
-
Custom Codecs:
- Implement
Http::ServerConnection/Http::ClientConnectioninterfaces. - Register codec factory. Used for dubbo, thrift, and other protocols wrapped as HTTP.
- Implement
To develop: Use bazel test //test/extensions/filters/network/http_connection_manager/... for HCM-specific tests. The IntegrationTest fixture in test/integration/ provides end-to-end testing with real listeners.