Open-Source Wikis

/

Envoy

/

Systems

/

Filter manager

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, decodeMetadata through the decoder chain in declared order.
  • Drives encodeHeaders, encodeData, encodeTrailers, encodeMetadata, encode1xxHeaders through 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 --> RunningEncoder

Each 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:

  1. Cancels the rest of the decoder chain.
  2. Constructs response headers (and optionally body) via LocalReplyImpl.
  3. Runs the full encoder chain so encoder filters see the synthetic response.
  4. 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 FilterManager per stream and feeds it codec callbacks.
  • Router. Uses a FilterManager of 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 StreamInfo updates 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 new FilterStatus value usually requires updating the manager's state machine.
  • Changing iteration semantics (e.g. early local replies during encode): heavy reading of filter_manager.cc is required; tests in test/common/http/filter_manager_test.cc are the canonical reference.

See also

Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.

Filter manager – Envoy wiki | Factory