Skip to content

Conversation

bplotnick
Copy link
Contributor

@bplotnick bplotnick commented Sep 22, 2025

Commit Message: router: Allow request header mutations and host header rewrite for mirroring
Additional Description:
Risk Level: Low
Testing: unit/integ tests
Docs Changes:
Release Notes: Added support for request_mutations in request_mirror_policies to enable header manipulation for mirror requests. Added support for host_rewrite_literal in request_mirror_policies to enable host header rewrite for mirror requests.
Platform Specific Features:

Signed-off-by: Ben Plotnick <[email protected]>
Signed-off-by: Ben Plotnick <[email protected]>
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 @mattklein123
CC @envoyproxy/api-watchers: FYI only for changes made to (api/envoy/|docs/root/api-docs/).

🐱

Caused by: #41178 was opened by bplotnick.

see: more, trace.

Signed-off-by: Ben Plotnick <[email protected]>
Signed-off-by: Ben Plotnick <[email protected]>
Copy link
Member

@wbpcode wbpcode left a comment

Choose a reason for hiding this comment

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

Thanks for the contribution and one comment to the API was added.

Comment on lines 889 to 908
// Specifies a list of HTTP headers that should be added to each mirrored request.
// Headers specified here take precedence over any headers with the same name
// from the original request. For more information, including details on header value syntax, see
// the documentation on :ref:`custom request headers
// <config_http_conn_man_headers_custom_request_headers>`.
repeated core.v3.HeaderValueOption request_headers_to_add = 7
[(validate.rules).repeated = {max_items: 1000}];

// Specifies a list of HTTP headers that should be removed from each request that is sent to the
// mirror cluster.
repeated string request_headers_to_remove = 8 [(validate.rules).repeated = {
items {string {well_known_regex: HTTP_HEADER_NAME strict: false}}
}];

// Indicates that during mirroring, the host header will be swapped with this value.
// :ref:`disable_shadow_host_suffix_append
// <envoy_v3_api_field_config.route.v3.RouteAction.RequestMirrorPolicy.disable_shadow_host_suffix_append>`
// is implicitly enabled if this field is set.
string host_rewrite_literal = 9
[(validate.rules).string = {well_known_regex: HTTP_HEADER_VALUE strict: false}];
Copy link
Member

Choose a reason for hiding this comment

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

Could upstream http filter be another choice? Or could we to reuse our message HeaderMutation then we can control the order of header addition/removal and also could support remove_on_match?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Good idea. Moved to using HeaderMutation

wrt upstream filters, they are equally applied to regular and shadowed requests. so I think the only way we could do this would be if we 1) applied separate filter chains for shadow or 2) had a special upstream filter (or perhaps extended the existing header mutation filter to understand whether the request was shadowed?)

Copy link
Member

Choose a reason for hiding this comment

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

wrt upstream filters, they are equally applied to regular and shadowed requests. so I think the only way we could do this would be if we 1) applied separate filter chains for shadow or 2) had a special upstream filter (or perhaps extended the existing header mutation filter to understand whether the request was shadowed?)

The upstream filters could configured at cluster, I think you only need a specific cluster for shadow traffic (and obviously we will have a shadow cluster, right?)

If possible, I will prefer to use the existing mechanism to address your requirements :)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'm only seeing upstream network filters at the cluster level, not http filters.

But it doesn't matter anyway. For both use-cases i need this for, we are mirroring to an existing cluster that has other uses. Imagine doing dual writes, but with two routes where one routes primary and mirrors to follower, and the other routes to follower and mirrors to primary.

Copy link
Member

Choose a reason for hiding this comment

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

Get it. Then I am OK to that.

@mattklein123 mattklein123 assigned wbpcode and unassigned mattklein123 Sep 23, 2025
Signed-off-by: Ben Plotnick <[email protected]>
Signed-off-by: Ben Plotnick <[email protected]>
Signed-off-by: Ben Plotnick <[email protected]>
Signed-off-by: Ben Plotnick <[email protected]>
Copy link
Member

@wbpcode wbpcode left a comment

Choose a reason for hiding this comment

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

Thanks for the update. The PR has very high quality and I only has some minor comments to the API and test.

Other thing is fine.

Comment on lines +890 to +894
// Specifies a list of header mutations that should be applied to each mirrored request.
// Header mutations are applied in the order they are specified. For more information, including
// details on header value syntax, see the documentation on :ref:`custom request headers
// <config_http_conn_man_headers_custom_request_headers>`.
repeated common.mutation_rules.v3.HeaderMutation request_mutations = 7
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
// Specifies a list of header mutations that should be applied to each mirrored request.
// Header mutations are applied in the order they are specified. For more information, including
// details on header value syntax, see the documentation on :ref:`custom request headers
// <config_http_conn_man_headers_custom_request_headers>`.
repeated common.mutation_rules.v3.HeaderMutation request_mutations = 7
// Specifies a list of header mutations that should be applied to each mirrored request.
// Header mutations are applied in the order they are specified. For more information, including
// details on header value syntax, see the documentation on :ref:`custom request headers
// <config_http_conn_man_headers_custom_request_headers>`.
repeated common.mutation_rules.v3.HeaderMutation request_headers_mutations = 7

In case possible trailer change in the future. :)

router_->onDestroy();
}

TEST_P(RouterShadowingTest, ShadowWithAdvancedHeaderMutations) {
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 this test is unnecessary because it should be covered by HeaderEvaluator self's test. We needn't to test these logic again and again at every position where the HeaderMutation is used.

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.

3 participants