envoyproxy/envoy
HTTP connection manager
The HTTP connection manager (HCM) is the network filter that turns a TCP (or QUIC) connection into a stream of HTTP requests, runs them through the L7 filter chain, and writes responses back. It is implemented as a network filter so it can plug into the standard listener pipeline, but it is the largest single component in Envoy and the entry point to almost all interesting L7 behaviour.
Purpose
For each connection routed to it, the HCM:
- Picks an HTTP/1, HTTP/2, or HTTP/3 codec based on the configured protocol or ALPN.
- Drives the codec to parse incoming bytes into headers/body/trailers.
- Per request, instantiates a fresh
FilterManagerand runs the configured chain of HTTP filters. - Manages timeouts (idle, request, stream), local replies, draining, GOAWAY, and overload signals.
- Generates request access logs and tracing spans.
Operator documentation is at envoyproxy.io/docs/envoy/latest/configuration/http/http_conn_man/http_conn_man.
Layout
The HCM is split between a network-filter shim and the implementation in source/common/http/:
| File | Role |
|---|---|
source/extensions/filters/network/http_connection_manager/config.cc |
Network filter factory: parses HttpConnectionManager proto, builds filter chain factories, instantiates ConnectionManagerImpl. |
source/common/http/conn_manager_impl.h and .cc |
The ConnectionManagerImpl class — the engine. |
source/common/http/filter_manager.h and .cc |
The L7 filter execution engine, used per-stream. |
source/common/http/conn_manager_utility.cc |
Helpers for populating request-id, x-forwarded-*, internal/external request classification. |
source/common/http/conn_manager_config.h |
The ConnectionManagerConfig interface that the filter chain queries. |
source/common/http/http1/, http2/ |
The HTTP/1.1 and HTTP/2 codecs (HTTP/3 codec is in source/common/quic/). |
conn_manager_impl.cc is the second-largest single file in the project at ~2,600 lines.
Key abstractions
| Type | Role |
|---|---|
ConnectionManagerImpl |
The network filter. Owns the codec and a list of in-flight streams. |
ActiveStream (inside conn_manager_impl.h) |
Per-request state: request/response headers, decoder/encoder filter chains, timers. |
FilterManager (filter_manager.h) |
Runs the decoder filter chain, then encoder, then trailers/data callbacks. |
ConnectionManagerConfig |
Read-only config the HCM consults — route configuration, tracing, access loggers, idle timeout, etc. |
ServerConnection (envoy/http/codec.h) |
Codec interface; one of Http1::ServerConnection, Http2::ServerConnection, Http3::ServerConnection. |
Filter (envoy/http/filter.h) |
The L7 filter base interface (decoder + encoder + trailers + on-destroy). |
Lifetime of a request
sequenceDiagram
participant N as Network filter chain
participant HCM as ConnectionManagerImpl
participant Codec as ServerConnection (h1/h2/h3)
participant FM as FilterManager
participant DF as Decoder filters
participant R as Router
participant U as Upstream
participant EF as Encoder filters
N->>HCM: onData(buffer)
HCM->>Codec: dispatch(buffer)
Codec->>HCM: newStream
HCM->>FM: create FilterManager + ActiveStream
Codec->>FM: decodeHeaders / decodeData / decodeTrailers
FM->>DF: run decoder chain
DF->>R: terminal filter (router)
R->>U: routerNewStream → upstream conn pool
U-->>R: response
R->>FM: encodeHeaders / encodeData / encodeTrailers
FM->>EF: run encoder chain
EF->>Codec: write response
Codec->>N: onWrite (response bytes)The flow is similar across protocols. HTTP/1 has at most one active stream per connection (with optional pipelining); HTTP/2 multiplexes many streams; HTTP/3 multiplexes streams over QUIC datagrams. The codec abstracts the differences and the FilterManager is identical regardless.
Codec selection
ConnectionManagerImpl::onData lazily creates a codec on the first byte:
- For HTTP/3, the QUIC layer creates the codec at connection time —
onConnectiontriggers codec creation. - For HTTP/1 and HTTP/2 the codec is selected from
HttpConnectionManager.codec_type. WithAUTO, ALPN selects HTTP/2 or HTTP/3, and the first request line on the wire selects HTTP/1 vs HTTP/2 (thePRIpreface).
The codec receives bytes and calls back into HCM with structured events (newStream, decodeHeaders, etc.).
Filter chain
The per-stream filter chain is constructed by a FilterChainFactory built at config time. Each filter's decodeHeaders is called in declared order; encoder filters run in reverse order. Filters can:
- Continue iteration immediately, returning
FilterHeadersStatus::Continue. - Stop iteration and resume later:
StopIteration, then calldecoder_callbacks_->continueDecoding(). - Generate a local reply and short-circuit the chain.
- Modify headers, body, or trailers.
- Make outbound requests via the async client (e.g.
ext_authz).
The terminal decoder filter is the router, which selects a cluster, picks a host, and forwards the request.
Headers and body buffers
Headers are stored in Http::HeaderMapImpl (source/common/http/header_map_impl.cc) — a custom container that interns common header names via the symbol table. Bodies use Buffer::WatermarkBuffer (source/common/buffer/watermark_buffer.cc) which signals back-pressure when high watermarks are reached.
Timeouts
The HCM enforces a layered set of timeouts:
| Timer | Configured by | Purpose |
|---|---|---|
request_timeout |
HttpConnectionManager.request_timeout |
Cap on receiving the entire request from the downstream client. |
request_headers_timeout |
HttpConnectionManager.request_headers_timeout |
Cap on receiving just the request headers. |
idle_timeout |
HttpConnectionManager.common_http_protocol_options.idle_timeout |
Connection-wide idle. |
stream_idle_timeout |
HttpConnectionManager.stream_idle_timeout |
Per-stream idle. |
drain_timeout |
HttpConnectionManager.drain_timeout |
After GOAWAY / drain, how long to wait before forcefully closing. |
The router applies its own route.timeout in addition.
Observability hooks
The HCM is the entry point for several cross-cutting concerns:
- Access logs. Configured
AccessLoginstances (source/extensions/access_loggers/) are invoked when the stream completes (and optionally periodically). The formatter system insource/common/formatter/backs the access-log substitution language. - Tracing.
Tracing::HttpTracerImpl(source/common/tracing/http_tracer_impl.cc) creates a span when the HCM entersdecodeHeaders. Tracer extensions (source/extensions/tracers/) export it. - Stats.
ConnectionManagerStats(counters likedownstream_rq_total,downstream_rq_2xx, …) live on every HCM instance. - Stream info. Each request's
StreamInfois the canonical record — used by access log formatters, filters, retry policies, and tracing.
Drain and GOAWAY
When the drain manager signals drain:
- HTTP/1 listeners add
Connection: closeto in-flight responses. - HTTP/2 sends a GOAWAY immediately, then a second one with the highest stream ID after
drain_timeout. - HTTP/3 sends a GOAWAY frame.
The HCM listens for the drain decision via a Network::DrainDecision reference passed at construction.
Overload integration
Server::OverloadManager (overload manager) can register overload actions with the HCM:
envoy.overload_actions.stop_accepting_requests— return 503.envoy.overload_actions.disable_http_keepalive— close after each response.envoy.overload_actions.reset_streams_using_excessive_memory— reset streams that buffer too much.
These reduce CPU/memory pressure without crashing.
Integration points
- Listener manager. HCM is the most common terminal network filter. It is configured by the HCM filter config factory in
source/extensions/filters/network/http_connection_manager/config.cc. - HTTP filters. The factory wires up the L7 chain. Each filter has its own factory under
source/extensions/filters/http/. - Router and cluster manager. The terminal filter calls into the cluster manager and connection pools.
- Tracers, access loggers, stat sinks. All consumed via the configured factory list.
- Codecs.
source/common/http/http1/,source/common/http/http2/,source/common/quic/.
Entry points for modification
- Adding a new HTTP filter: create a directory under
source/extensions/filters/http/<name>/, register a factory, add toextensions_build_config.bzl. Read patterns and conventions and an existing simple filter (e.g.header_mutation) for the boilerplate. - Modifying request lifecycle: read
conn_manager_impl.cc—ActiveStream::decodeHeaders,encodeHeaders, and the timer setup are the central paths. - Modifying filter chain semantics: read
filter_manager.cc. - Adding a header behaviour: most goes through
ConnectionManagerUtility(conn_manager_utility.cc).
See also
- Filter manager — the per-stream chain runner.
- Router — the terminal HTTP filter.
- HTTP filters — the broader L7 filter family.
- Tracing — span lifecycle hooks here.
- Access logging — per-request log emission.
Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.