Skip to content

Conversation

@wbpcode
Copy link
Member

@wbpcode wbpcode commented Jan 8, 2026

Commit Message: http: new filter chain filter
Additional Description:

  • New filter to configured multiple sub filter chains and allow the route to select one or provide a inline sub filter chain.

This PR gives the actual per route level filter chain support. We only need to ensure most filters could support the createFilterFactoryFromProtoWithServerContext.

This filter is a little similar to composite, but with following difference:

  • provides full feature sub filter chain support.
  • not as flexible as composite filter, only the initial route could be used to help to select the sub filter chain, but more easier to use and more robust for lots scenarios.

Risk Level: low. new filter.
Testing: unit/integration.
Docs Changes: added.
Release Notes: added.
Platform Specific Features: n/a.

Signed-off-by: wbpcode/wangbaiping <[email protected]>
@repokitteh-read-only
Copy link

CC @envoyproxy/api-shepherds: Your approval is needed for changes made to (api/envoy/|docs/root/api-docs/).
envoyproxy/api-shepherds assignee is @adisuissa
CC @envoyproxy/api-watchers: FYI only for changes made to (api/envoy/|docs/root/api-docs/).

🐱

Caused by: #42912 was opened by wbpcode.

see: more, trace.

@wbpcode wbpcode assigned agrawroh and unassigned adisuissa Jan 8, 2026
Signed-off-by: wbpcode/wangbaiping <[email protected]>
@wbpcode
Copy link
Member Author

wbpcode commented Jan 9, 2026

I like it, CI are all green.

Copy link
Contributor

@adisuissa adisuissa left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks.
Left a few high-level comments.
This should probably be reviewed by the rest of the api shepherds.
cc @markdroth


// Map of named filter chains. The key is an arbitrary name assigned to the filter chain.
// These named filter chains can be referenced by the per-route configuration using
// the filter_chain_name field in FilterChainConfigPerRoute.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think there's an implementation detail that should be highlighted here:
all the filters (in all the chains) will be initialized even if not used.
This will cause some confusion especially as some filters of the same type that appear in two different chains will not have a shared state.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will update the comment to make it more clear.

// Each filter in the chain will process the request/response in sequence.
// At least one filter must be specified.
// [#extension-category: envoy.filters.http]
repeated config.core.v3.TypedExtensionConfig filters = 1
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As this is a filter chain, what were the design tradeoffs between typed-extension and Filter types here?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, what you mean by Filter types? We prefer to use the TypedExtensionConfig in most cases I think?

// If specified, this filter chain takes precedence over filter_chain_name.
FilterChain filter_chain = 1;

// Name of the filter chain to be applied on this route. This name should match
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm trying to understand what's the difference between this and the Composite filter, and all I see is that the matching is done on a route override rather than in the HCM filter chain. Is that correct?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see that it was referenced in the PR description:

This filter is a little similar to composite, but with following difference:

  • provides full feature sub filter chain support.
  • not as flexible as composite filter, only the initial route could be used to help to select the sub filter chain, but more easier to use and more robust for lots scenarios.

What I wonder is whether the referencing by name can be done with a different design that allows referencing global named filters which will help multi-tenant deployments that have shared filters across listeners.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What I wonder is whether the referencing by name can be done with a different design that allows referencing global named filters which will help multi-tenant deployments that have shared filters across listeners.

I think it's a little hard because we need to add a filter chain map at the bootstrap that means we cannot update it dynamically by the xDS?

Copy link
Member

@agrawroh agrawroh left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks great! Just some minor comments/questions. Thank you so much for working on this. We really need this to organize our filter chains.

//
// This field is optional. If not specified and no route-level configuration matches,
// the filter will pass through without applying any additional filters.
FilterChain filter_chain = 1;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we add a warning (and also validation) that configuring envoy.filters.http.filter_chain recursively within its own filter chains is not supported.

// Each filter in the chain will process the request/response in sequence.
// At least one filter must be specified.
// [#extension-category: envoy.filters.http]
repeated config.core.v3.TypedExtensionConfig filters = 1
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should also add a note on how the filters across all the named chains and the default chain are compiled and initialized. AFAIK they are all initialized at configuration time, regardless of runtime usage. Is that right?

Copy link
Member Author

@wbpcode wbpcode Jan 19, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not sure whether it make sense or not. Because all filters absolutely will be initialized/loaded because it's part of configuration loading? So, I think we may needn't that redundant description?

}

// Helper to process filter config and create filter factories
Http::FilterChainUtility::FilterFactoriesList createFilterFactoriesFromConfig(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmmm, looks like we have two versions of createFilterFactoriesFromConfig with different arguments. Is it possible to create a template helper?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmmm, it's some difference between the server context version and factory context version. Template may couldn't simplify too much.

- name: mock_filter
typed_config:
"@type": type.googleapis.com/google.protobuf.Struct
- name: another_filter
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like this is unregistered and currently per the implementation if a per-route config references a non-existent filter chain name, we seems to be silently falls back to the default. Do we need to do any config-time validation or have any counter which records this?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Stats SGTM. I don't think we could do any validation at config-time because the route configuration could be shared across listeners.

// Each filter in the chain will process the request/response in sequence.
// At least one filter must be specified.
// [#extension-category: envoy.filters.http]
repeated config.core.v3.TypedExtensionConfig filters = 1
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm assuming that we won't be able to support ECDS here. Is that right?

Copy link
Member Author

@wbpcode wbpcode Jan 19, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, because TypedExtensionConfig rather then the HttpFilter is used here and I have no plan to make the feature too complex.

@@ -0,0 +1,107 @@
#include "source/extensions/filters/http/filter_chain/filter.h"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Our main filter chain also validates the terminal filters but our new filter does not. It's possible that the users could configure the router filter inside a sub-chain which would lead to an undefined behavior.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah. It's possible. I will document it rather than to make the code more complex.

Signed-off-by: wbpcode <[email protected]>
Signed-off-by: wbpcode/wangbaiping <[email protected]>

.. code-block:: yaml

http_filters:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does WASM filter works with this per route config?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants