Skip to content

fix: lua filters from EnvoyExtensionPolicy can now run after ext_proc on the response path#2266

Open
yuehaii wants to merge 6 commits into
envoyproxy:mainfrom
yuehaii:lua-filter-order
Open

fix: lua filters from EnvoyExtensionPolicy can now run after ext_proc on the response path#2266
yuehaii wants to merge 6 commits into
envoyproxy:mainfrom
yuehaii:lua-filter-order

Conversation

@yuehaii

@yuehaii yuehaii commented Jun 21, 2026

Copy link
Copy Markdown

Description
lua filters are always ran before ext_proc on responses. any content mutation done in the filter is lost. lua filter order prevents running after ext_proc on responses.

Related Issues/PRs (if applicable)
Fixes #2247

Special notes for reviewers (if applicable)
introduces a new annotation on EnvoyExtensionPolicy that lets users declare the desired filter ordering relative to the ext_proc. during XDS translation (PostTranslateModify), the extension server reads the annotation and repositions the named filters in each listener's HCM filter chain accordingly.

the new annotation "aigateway.envoyproxy.io/filter-order" value is a comma-separated ordered sequence of filter type tokens, with the special token ExtProc acting as the pivot representing the ext_proc filter.

  • tokens listed before ExtProc: filters placed before ext_proc on the request path (run after ext_proc on responses)
  • tokens listed after ExtProc: filters placed after ext_proc on the request path (run before ext_proc on responses)
  • Filters not listed: keep their default position, after ext_proc on request path.

if "aigateway.envoyproxy.io/default-filter-order" is set as the value of DefaultFilterOrderAnnotation. it will places all of the policy's extension filters before the ext_proc.

the k8s List call for EnvoyExtensionPolicy is served from the controller-runtime in-memory cache. it does not hit the k8s api server on every xDS translation.

…oll the lua filter order in filter chain.

by default, it is after the ext_proc filter. setting it as "before-extproc" will move the lua filter before ext_proc filter. so in response, it will be executed after ext_proc filter.

Signed-off-by: hai.yue <20416005+yuehaii@users.noreply.github.com>
@yuehaii
yuehaii requested a review from a team as a code owner June 21, 2026 09:56
@dosubot dosubot Bot added the size:L This PR changes 100-499 lines, ignoring generated files. label Jun 21, 2026
Signed-off-by: hai.yue <20416005+yuehaii@users.noreply.github.com>
@yuehaii

yuehaii commented Jul 7, 2026

Copy link
Copy Markdown
Author

hi @nacx , good day. could you please help review this pull request when it is convenient? thanks.

Signed-off-by: hai.yue <20416005+yuehaii@users.noreply.github.com>
@codecov-commenter

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 81.08108% with 14 lines in your changes missing coverage. Please review.
✅ Project coverage is 84.85%. Comparing base (786b4b9) to head (3713c8b).
⚠️ Report is 35 commits behind head on main.

Files with missing lines Patch % Lines
internal/extensionserver/post_translate_modify.go 81.08% 8 Missing and 6 partials ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #2266      +/-   ##
==========================================
+ Coverage   84.70%   84.85%   +0.15%     
==========================================
  Files         144      144              
  Lines       21204    21369     +165     
==========================================
+ Hits        17960    18133     +173     
+ Misses       2162     2146      -16     
- Partials     1082     1090       +8     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@nacx

nacx commented Jul 9, 2026

Copy link
Copy Markdown
Member

Thanks for raising.

I would like to generalize the problem statement a bit and put more thought into this. Today, the filter order is hardcoded in the code and cannot be modified, and that has been a challenge already for several users.

This PR tackles specifically hte problem for Lua, but I think we can generalize the solution to apply to the rest of the filters that can be configured with an `EnvoyExtensionPolicy, as Wasm or dynamic module users may be facing the same problems.

Several things to consider and discuss:

  • We need to make sure the lists of EnvoyExtensionPolicies are cached, as we don't wanna go to the k8s api server every time we need to resolve XDS configs to send to the Envoy pods.
  • We want to centralize the ordering logic in a single place. Most of the logic lives today in the insertAIGatewayExtProcFilter method, and having ordering logic spread across different places will make it very hard to maintain and reason about.
  • When generalizing this to other types of extensions (to provide a consistent API experience to users with semantics shared across), we also need to reason about ext-proc extensions.

@missBerg missBerg added the area/operations Deployment, Helm, platform config, k8s limits label Jul 13, 2026
yuehaii added 3 commits July 19, 2026 21:29
Signed-off-by: hai.yue <20416005+yuehaii@users.noreply.github.com>
Signed-off-by: hai.yue <20416005+yuehaii@users.noreply.github.com>
Signed-off-by: hai.yue <20416005+yuehaii@users.noreply.github.com>
@yuehaii

yuehaii commented Jul 22, 2026

Copy link
Copy Markdown
Author

Thanks for raising.

I would like to generalize the problem statement a bit and put more thought into this. Today, the filter order is hardcoded in the code and cannot be modified, and that has been a challenge already for several users.

This PR tackles specifically hte problem for Lua, but I think we can generalize the solution to apply to the rest of the filters that can be configured with an `EnvoyExtensionPolicy, as Wasm or dynamic module users may be facing the same problems.

Several things to consider and discuss:

  • We need to make sure the lists of EnvoyExtensionPolicies are cached, as we don't wanna go to the k8s api server every time we need to resolve XDS configs to send to the Envoy pods.
  • We want to centralize the ordering logic in a single place. Most of the logic lives today in the insertAIGatewayExtProcFilter method, and having ordering logic spread across different places will make it very hard to maintain and reason about.
  • When generalizing this to other types of extensions (to provide a consistent API experience to users with semantics shared across), we also need to reason about ext-proc extensions.

hi @nacx, good day. can you please review the pull request again? I introduced a new annotation on EnvoyExtensionPolicy that lets users declare the desired filter ordering relative to the ext_proc.
during XDS translation (PostTranslateModify), the extension server reads the annotation and repositions the named filters in each listener's HCM filter chain accordingly.

the new annotation "aigateway.envoyproxy.io/filter-order" value is a comma-separated ordered sequence of filter type tokens, with the special token ExtProc acting as the pivot representing the ext_proc filter.

  • tokens listed before ExtProc: filters placed before ext_proc on the request path (run after ext_proc on responses)
  • tokens listed after ExtProc: filters placed after ext_proc on the request path (run before ext_proc on responses)
  • Filters not listed: keep their default position, after ext_proc on request path.

if "aigateway.envoyproxy.io/default-filter-order" is set as the value of DefaultFilterOrderAnnotation. it will places all of the policy's extension filters before the ext_proc.

the k8s List call for EnvoyExtensionPolicy is served from the controller-runtime in-memory cache. it does not hit the k8s api server on every xDS translation.

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

Labels

area/operations Deployment, Helm, platform config, k8s limits size:L This PR changes 100-499 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Lua filter order prevents running after ext_proc on responses

4 participants