HTTP filters
Much like the network level filter stack, Envoy supports an HTTP level filter stack within the connection manager.
Filters can be written that operate on HTTP level messages without knowledge of the underlying physical protocol (HTTP/1.1, HTTP/2, etc.) or multiplexing capabilities.
HTTP filters can be downstream HTTP filters, associated with a given listener and doing stream processing on each downstream request before routing, or upstream HTTP filters, associated with a given cluster and doing stream processing once per upstream request, after the router filter.
There are three types of HTTP level filters:
- Decoder
Decoder filters are invoked when the connection manager is decoding parts of the request stream (headers, body, and trailers).
- Encoder
Encoder filters are invoked when the connection manager is about to encode parts of the response stream (headers, body, and trailers).
- Decoder/Encoder
Decoder/Encoder filters are invoked both when the connection manager is decoding parts of the request stream and when the connection manager is about to encode parts of the response stream.
The API for HTTP level filters allows the filters to operate without knowledge of the underlying protocol.
Like network level filters, HTTP filters can stop and continue iteration to subsequent filters. This allows for more complex scenarios such as health check handling, calling a rate limiting service, buffering, routing, generating statistics for application traffic such as DynamoDB, etc.
HTTP level filters can also share state (static and dynamic) among themselves within the context of a single request stream. Refer to data sharing between filters for more details.
Tip
See the HTTP filters configuration and protobuf sections for reference documentation.
See here for included filters.
Filter ordering
Filter ordering in the http_filters field matters. If filters are configured in the following order (and assuming all three filters are decoder/encoder filters):
http_filters:
- A
- B
# The last configured filter has to be a terminal filter, as determined by the
# NamedHttpFilterConfigFactory::isTerminalFilterByProto(config, context) function. This is most likely the router
# filter.
- C
The connection manager will invoke decoder filters in the order: A
, B
, C
.
On the other hand, the connection manager will invoke encoder filters in the reverse
order: C
, B
, A
.
Conditional filter configuration
There is some support for having the filter configuration used change based on the incoming request. See the composite filter for details on how to configure a match tree that can resolve filter configuration to use for a given request.
Filter route mutation
During downstream HTTP filter chain processing, when decodeHeaders()
is invoked by a filter, the
connection manager performs route resolution and sets a cached route pointing to an upstream
cluster.
Downstream HTTP filters have the capability to directly mutate this cached route after route resolution, via the
setRoute
callback and DelegatingRoute
mechanism.
A filter may create a derived/child class of DelegatingRoute
to override specific methods
(for example, the route’s timeout value or the route entry’s cluster name) while preserving
the rest of the properties/behavior of the base route that the DelegatingRoute
wraps around.
Then, setRoute
can be invoked to manually set the cached route to this DelegatingRoute
instance. An example of such a derived class can be found in ExampleDerivedDelegatingRoute.
If no other filters in the chain modify the cached route selection (for example, a common operation
that filters do is clearRouteCache()
, and setRoute
will not survive that), this route
selection makes its way to the router filter which finalizes the upstream cluster that the request
will be forwarded to.
Route specific config
The per filter config map can be used to provide route or virtual host or route configuration specific config for http filters.
The key of the per filter config map should match the filter config name.
For example, given following http filter config:
http_filters:
- name: custom-filter-name-for-lua # Custom name be used as filter config name
typed_config: { ... }
- name: envoy.filters.http.buffer # Canonical name be used as filter config name
typed_config: { ... }
The custom-filter-name-for-lua
and envoy.filters.http.buffer
will be used as the key to lookup
related per filter config.
For the first custom-filter-name-for-lua
filter, if no related entry are found by
custom-filter-name-for-lua
, we will downgrade to try the canonical filter name envoy.filters.http.lua
.
This downgrading is for backward compatibility and could be disabled by setting the runtime flag
envoy.reloadable_features.no_downgrade_to_canonical_name
to true
explicitly.
For the second envoy.filters.http.buffer
filter, if no related entry are found by
envoy.filters.http.buffer
, we will not try to downgrade because canonical filter name is the same as
the filter config name.
Warning
Downgrading to canonical filter name is deprecated and will be removed soon. Please ensure the key of the per filter config map matches the filter config name exactly and don’t rely on the downgrading behavior.
Use of per filter config map is filter specific. See the HTTP filter documentation for if and how it is utilized for every filter.
Route based filter chain
There is support for having different filter chains for different routes. There are two different modes for this:
Disabling a filter in the filter chain for specific routes.
Overriding a filter in the filter chain that is disabled by default and enabling it for specific routes.
By default, the filter chain is the same for all routes and all filters are enabled. However, a filter can be disabled for specific routes by using the FilterConfig and setting the disabled field in the per filter config map in the route configuration. See the Route specific config section for more details.
For example, given following http filter config:
http_filters:
- name: buffer
typed_config: { ... }
- name: lua
typed_config: { ... }
Both the buffer
and lua
filters are enabled by default. If we want to disable the buffer
filter
for a specific route, we can set the per filter config map in the route configuration:
typed_per_filter_config:
buffer:
"@type": type.googleapis.com/envoy.config.route.v3.FilterConfig
disabled: true
In addition, we can set a filter to be disabled by default by setting the disabled field in the HttpFilter configuration and then enable it for specific routes if needed.
For example, given following http filter config:
http_filters:
- name: buffer
typed_config: { ... }
disabled: true
- name: lua
typed_config: { ... }
disabled: true
Both the buffer
and lua
filters are disabled by default. If we want to enable one of them
for a specific route, we can set per filter config map in the route configuration:
typed_per_filter_config:
lua:
"@type": type.googleapis.com/envoy.extensions.filters.http.lua.v3.LuaPerRoute
name: my_lua_script
Legitimate route-specific configuration for filter (like the above lua
filter) is valid way to
enable the filter for the route.