Skip to content

feat(listenerpolicy): allow configuring Envoy local replies#14146

Merged
puertomontt merged 7 commits into
kgateway-dev:mainfrom
marvin-roesch:feat/listener-local-reply
Jun 16, 2026
Merged

feat(listenerpolicy): allow configuring Envoy local replies#14146
puertomontt merged 7 commits into
kgateway-dev:mainfrom
marvin-roesch:feat/listener-local-reply

Conversation

@marvin-roesch

@marvin-roesch marvin-roesch commented Jun 2, 2026

Copy link
Copy Markdown
Contributor

Description

Motivation: Envoy by default produces plaintext local replies for errors etc., which can lead to unexpected output on endpoints that expose e.g. a JSON-based API. Being able to configure a custom default format but also adjusting individual replies based on filters (e.g. changing 403 replies from RBAC filters into 404s) is very helpful for these scenarious.

What changed: We implement an extension of the ListenerPolicy HTTP settings that maps to Envoy's local reply config. It shares types with the access log filter config as these are also shared in Envoy's API.

Related issues: Closes #3466

Change Type

/kind feature

Changelog

Added Envoy local reply configuration to `ListenerPolicy`

Additional Notes

This has some overlap with #13436. The custom response filter can cover what the local reply config does using the newly introduced envoy.matching.inputs.local_reply input. However, there currently is a bug (envoyproxy/envoy#45346`) where Envoy does not expose the original local reply body within that filter, so it has limited utility, unfortunately.

This does not prevent a policy extension for the custom response filter to be introduced later, however. The features complement each other, where the local reply config applies to all replies generated by a listener, including those not covered by any filter.

Copilot AI review requested due to automatic review settings June 2, 2026 10:03
@marvin-roesch
marvin-roesch requested a review from a team as a code owner June 2, 2026 10:03
@gateway-bot gateway-bot added kind/feature Categorizes issue or PR as related to a new feature. release-note labels Jun 2, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Note

Copilot was unable to run its full agentic suite in this review.

Adds support for configuring Envoy's LocalReplyConfig via ListenerPolicy.httpSettings.localReplies and HTTPListenerPolicy.localReplies. Refactors shared body-format and header-filter helpers into reusable utilities and moves BodyFormat into the shared API package.

Changes:

  • New LocalReplyConfig/LocalReplyMapper types and translation to Envoy LocalReplyConfig (with merge support across HTTP listener policies).
  • Extracts BodyFormat, header-filter conversion, and access-log filter conversion into shared pluginutils/common.go helpers and updates DirectResponse + TrafficPolicy header modifiers to use them.
  • Adds CRD updates (including int32uint32 for ComparisonFilter value), translator test fixtures, and an e2e test suite for local replies.

Reviewed changes

Copilot reviewed 23 out of 26 changed files in this pull request and generated 7 comments.

Show a summary per file
File Description
api/v1alpha1/kgateway/listener_policy_types.go Adds LocalReplyConfig/LocalReplyMapper; changes ComparisonFilter Value to uint32.
api/v1alpha1/kgateway/direct_response_types.go Moves BodyFormat to shared package and reuses it.
api/v1alpha1/shared/shared_types.go Introduces shared BodyFormat type.
pkg/kgateway/extensions2/pluginutils/pluginutils.go Adds EnvoyBodyFormat helper.
pkg/kgateway/extensions2/pluginutils/headers.go Adds ConvertHeaderFilter, ConvertMutationsToOptions, resolveHeader.
pkg/kgateway/extensions2/plugins/trafficpolicy/header_modifiers.go Refactored to use shared header-filter helpers.
pkg/kgateway/extensions2/plugins/directresponse/direct_response_plugin.go Uses pluginutils.EnvoyBodyFormat.
pkg/kgateway/extensions2/plugins/listenerpolicy/local_reply_converter.go New translator for local reply config.
pkg/kgateway/extensions2/plugins/listenerpolicy/common.go Moves access-log filter translation here for reuse.
pkg/kgateway/extensions2/plugins/listenerpolicy/access_logging_converter.go Removes filter translation now in common.go.
pkg/kgateway/extensions2/plugins/listenerpolicy/http.go Wires localReplyConfig into IR/Equals.
pkg/kgateway/extensions2/plugins/listenerpolicy/listener_plugin.go Applies LocalReplyConfig to HCM.
pkg/kgateway/extensions2/plugins/listenerpolicy/merge_http.go Adds merge function for local reply config.
install/helm/kgateway-crds/templates/gateway.kgateway.dev_httplistenerpolicies.yaml CRD updates for new fields and uint32 value format.
pkg/kgateway/translator/gateway/gateway_translator_test.go New translator tests for local reply config.
pkg/kgateway/translator/gateway/testutils/inputs/{,http}listenerpolicy/local-reply-config.yaml Translator test inputs.
pkg/kgateway/translator/gateway/testutils/outputs/{,http}listenerpolicy/local-reply-config.yaml Expected translator outputs.
test/e2e/features/listener_policy/{suite,types}.go E2E test cases and manifest registration.
test/e2e/features/listener_policy/testdata/{listener-policy-local-reply-config,local-reply-httproute}.yaml E2E manifests.
Files not reviewed (2)
  • api/v1alpha1/kgateway/zz_generated.deepcopy.go: Language not supported
  • api/v1alpha1/shared/zz_generated.deepcopy.go: Language not supported

Comment thread pkg/kgateway/extensions2/pluginutils/headers.go Outdated
Comment thread test/e2e/features/listener_policy/suite.go Outdated
Comment thread test/e2e/features/listener_policy/suite.go Outdated
Comment thread test/e2e/features/listener_policy/testdata/local-reply-httproute.yaml Outdated
Comment thread api/v1alpha1/shared/shared_types.go Outdated
Comment thread pkg/kgateway/extensions2/pluginutils/pluginutils.go
Comment thread pkg/kgateway/extensions2/plugins/listenerpolicy/merge_http.go
@marvin-roesch
marvin-roesch force-pushed the feat/listener-local-reply branch from 5dc034e to 9dff0bb Compare June 2, 2026 10:08
Comment thread pkg/kgateway/extensions2/pluginutils/headers.go Outdated
@marvin-roesch
marvin-roesch force-pushed the feat/listener-local-reply branch 2 times, most recently from 509a702 to 7e8e3b3 Compare June 3, 2026 07:23
@marvin-roesch
marvin-roesch requested a review from Copilot June 3, 2026 08:01

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 29 out of 32 changed files in this pull request and generated 7 comments.

Files not reviewed (2)
  • api/v1alpha1/kgateway/zz_generated.deepcopy.go: Language not supported
  • api/v1alpha1/shared/zz_generated.deepcopy.go: Language not supported

Comment thread pkg/kgateway/extensions2/pluginutils/headers_test.go
Comment thread pkg/kgateway/extensions2/pluginutils/headers_test.go
Comment thread pkg/kgateway/extensions2/pluginutils/headers.go
Comment thread pkg/kgateway/extensions2/pluginutils/pluginutils.go
Comment thread pkg/kgateway/extensions2/pluginutils/pluginutils.go
Comment thread api/v1alpha1/kgateway/listener_policy_types.go
@marvin-roesch

Copy link
Copy Markdown
Contributor Author

/retest

@mcmarkj

mcmarkj commented Jun 9, 2026

Copy link
Copy Markdown

This is a feature we really would appreciate. Any way of nudging it along to release?

PS. Thank you for your work @marvin-roesch

@davidjumani

Copy link
Copy Markdown
Contributor

@marvin-roesch can you please rebase with the latest main? Thanks

@marvin-roesch
marvin-roesch force-pushed the feat/listener-local-reply branch from cb1f4b2 to 5a5d1ed Compare June 10, 2026 12:06
@marvin-roesch

Copy link
Copy Markdown
Contributor Author

Rebased, @davidjumani.

@puertomontt
puertomontt added this pull request to the merge queue Jun 16, 2026
@github-merge-queue
github-merge-queue Bot removed this pull request from the merge queue due to failed status checks Jun 16, 2026
@marvin-roesch
marvin-roesch force-pushed the feat/listener-local-reply branch from 5a5d1ed to 252957f Compare June 16, 2026 12:34
@marvin-roesch
marvin-roesch force-pushed the feat/listener-local-reply branch from 252957f to 12baa37 Compare June 16, 2026 12:34
@marvin-roesch

Copy link
Copy Markdown
Contributor Author

@puertomontt I have rebased onto main and fixed the compilation issue that got introduced.

Signed-off-by: Marvin Rösch <[email protected]>
@marvin-roesch
marvin-roesch force-pushed the feat/listener-local-reply branch from 12baa37 to 7876b0a Compare June 16, 2026 13:19
@marvin-roesch

Copy link
Copy Markdown
Contributor Author

/retest

@puertomontt
puertomontt added this pull request to the merge queue Jun 16, 2026
Merged via the queue into kgateway-dev:main with commit e341a61 Jun 16, 2026
35 of 37 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

kind/feature Categorizes issue or PR as related to a new feature. release-note

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Expose config for Envoy's local reply mapper

6 participants