envoyproxy/envoy
Filter manager
The HTTP filter manager is the per-stream engine that runs the L7 filter chain. It is constructed once per request by the HTTP connection manager, and it dispatches headers, data, trailers, and metadata between filters in both directions. The implementation lives in source/common/http/filter_manager.h and source/common/http/filter_manager.cc — at ~88k lines of .cc, one of the largest files in the project.
Purpose
Given a chain of decoder filters and a chain of encoder filters built at config time, the filter manager:
- Drives
decodeHeaders,decodeData,decodeTrailers,decodeMetadatathrough the decoder chain in declared order. - Drives
encodeHeaders,encodeData,encodeTrailers,encodeMetadata,encode1xxHeadersthrough the encoder chain in reverse declared order. - Lets a filter pause iteration (
StopIteration) and resume later asynchronously. - Lets a filter generate a local reply that short-circuits the rest of the decoder chain and runs only the encoder chain.
- Buffers data when filters need to see complete bodies and applies watermarks for back-pressure.
- Manages per-filter access logging and stream info accounting.
Why it's separate from the HCM
ConnectionManagerImpl owns the codec, connection-wide concerns (idle timeout, drain, GOAWAY), and stream creation. FilterManager owns the per-stream filter-chain state machine. The split lets the same FilterManager be used by:
- The HCM for normal HTTP requests.
- The router for the upstream filter chain.
- Test fixtures that exercise filter behaviour without a real codec.
Key abstractions
| Type | Role |
|---|---|
FilterManager (filter_manager.h) |
Owns the chain state, runs decoder/encoder iterations. |
ActiveStreamFilterBase (and Decoder/Encoder subclasses) |
Wraps a single filter; tracks "iteration stopped" / "buffered" / "ended" state. |
FilterManagerCallbacks |
The interface the FilterManager calls to hand encoded bytes back to the HCM/codec. |
StreamFilterBase (envoy/http/filter.h) |
The base filter interface every L7 filter implements. |
LocalReply (source/common/local_reply/local_reply.h) |
Generates short-circuit responses with templated body/headers. |
Iteration state machine
stateDiagram-v2
[*] --> NotStarted
NotStarted --> RunningDecoder: decodeHeaders called
RunningDecoder --> Stopped: filter returns StopIteration
Stopped --> RunningDecoder: continueDecoding
RunningDecoder --> RouterReached: terminal filter
RouterReached --> AwaitingResponse
AwaitingResponse --> RunningEncoder: encodeHeaders
RunningEncoder --> StoppedEnc: filter returns StopIteration
StoppedEnc --> RunningEncoder: continueEncoding
RunningEncoder --> Done: end_stream true
Done --> [*]
RunningDecoder --> LocalReply: filter sends local reply
LocalReply --> RunningEncoderEach filter has a small bit of state: did it stop iteration? If it stopped on data, did it ask to buffer? Did it ask for trailers to be held? The filter manager honours these flags and resumes iteration when the filter calls decoder_callbacks_->continueDecoding().
Buffering and watermarks
Filters can opt into buffered semantics:
setDecoderBufferLimit(N)— tell the manager to buffer up to N bytes of body before passing to the next filter.- The manager wires a
Buffer::WatermarkBuffer(source/common/buffer/watermark_buffer.cc) for each filter and applies high/low watermarks to back-pressure the codec. decoder_callbacks_->addDecodedData(data, true /* streaming */)allows a filter to inject bytes mid-chain.
The watermarking is what stops a slow filter or upstream from being overwhelmed by a fast downstream client.
Local replies
A filter can short-circuit by calling decoder_callbacks_->sendLocalReply(...). The filter manager:
- Cancels the rest of the decoder chain.
- Constructs response headers (and optionally body) via
LocalReplyImpl. - Runs the full encoder chain so encoder filters see the synthetic response.
- Notifies the codec to write the response.
The generic local-reply machinery is in source/common/local_reply/local_reply.cc; custom mappers can rewrite local-reply responses (e.g. via the local_reply_config in HCM).
Async filters
Filters that issue out-of-band requests (ext_authz, jwt_authn JWKS fetch, oauth2 token exchange) follow a standard pattern:
FilterHeadersStatus decodeHeaders(RequestHeaderMap&, bool) override {
state_ = State::CallingExternal;
callout_->invoke(); // returns immediately
return FilterHeadersStatus::StopIteration;
}
void onCalloutComplete(...) {
state_ = State::Complete;
decoder_callbacks_->continueDecoding();
}The filter manager doesn't time these out — the timer comes from the HCM or the per-route timeout.
Filter chain building
The factory list comes from the HCM config (source/extensions/filters/network/http_connection_manager/config.cc). Each entry is a Server::Configuration::NamedHttpFilterConfigFactory registered for a specific filter name. At stream start, the filter manager iterates the factory list and calls createFilterChain(callbacks), which adds filter instances to the manager.
Per-route filter overrides allow individual filters to be disabled or reconfigured at the route level via typed_per_filter_config.
Match-delegate filters
The match_delegate and composite filters use a matching tree (xDS Matching API in source/common/matcher/) to decide whether and which filter runs. The filter manager treats them as ordinary filters; the matching happens inside the delegate.
Integration points
- HTTP connection manager. Constructs a
FilterManagerper stream and feeds it codec callbacks. - Router. Uses a
FilterManagerof its own for the upstream filter chain. - Filter implementations. Every filter under
source/extensions/filters/http/is plugged in here. - Tracing and access logs. The filter manager hooks
StreamInfoupdates that drive access log emission.
Entry points for modification
- Adding filter primitives (e.g. a new callback or status return value): the public interface is in
envoy/http/filter.h. Adding a newFilterStatusvalue usually requires updating the manager's state machine. - Changing iteration semantics (e.g. early local replies during encode): heavy reading of
filter_manager.ccis required; tests intest/common/http/filter_manager_test.ccare the canonical reference.
See also
- HTTP connection manager — the consumer.
- HTTP filters — what the manager runs.
- Router — the standard terminal filter.
Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.