Skip to content

api: add maxRequestHeaderBytes and host normalization to ClientTrafficPolicy - #8825

Closed
albsga4 wants to merge 9 commits into
envoyproxy:mainfrom
albsga4:feat/ctp-max-request-headers-strip-port
Closed

api: add maxRequestHeaderBytes and host normalization to ClientTrafficPolicy#8825
albsga4 wants to merge 9 commits into
envoyproxy:mainfrom
albsga4:feat/ctp-max-request-headers-strip-port

Conversation

@albsga4

@albsga4 albsga4 commented Apr 22, 2026

Copy link
Copy Markdown
Contributor

What type of PR is this?

api: add maxRequestHeaderBytes and host.stripPortMode fields to ClientTrafficPolicy

What this PR does / why we need it:

Two common HttpConnectionManager settings currently require EnvoyPatchPolicy with fragile jsonPath expressions to configure:

  1. max_request_headers_kb — the default 60 KiB limit is too small for many production use cases (large Authorization headers, cookies, etc.)
  2. strip_port_mode — clients sending Host: example.com:443 don't match routes defined without ports

This PR adds native ClientTrafficPolicy fields for both:

apiVersion: gateway.envoyproxy.io/v1alpha1
kind: ClientTrafficPolicy
spec:
  headers:
    maxRequestHeaderBytes: 80Ki
  host:
    stripPortMode: Any

headers.maxRequestHeaderBytes (resource.Quantity)

  • Maps to Envoy max_request_headers_kb on the HCM
  • Accepts Kubernetes resource quantities (80Ki, 100Ki, 1Mi, or raw bytes like 81920)
  • Validated to be at least 1Ki (1024 bytes) — values below return an error
  • Follows the same pattern as connection.socketBufferLimit (Quantity in API, uint32 in IR)

host.stripPortMode (Enum: Any | Matching)

  • New host section parallel to the existing path section (path normalizes path, host normalizes host)
  • Any maps to Envoy strip_any_host_port (strips port unconditionally)
  • Matching maps to Envoy strip_matching_host_port (strips only when port matches listener)
  • Nil means no stripping (Envoy default)

Changes:

  • api/v1alpha1/clienttrafficpolicy_types.goMaxRequestHeaderBytes in HeaderSettings, new HostSettings struct with StripPortMode enum
  • internal/ir/xds.goMaxRequestHeadersKB *uint32 in HeaderSettings, HostSettings with typed StripPortMode + constants
  • internal/gatewayapi/clienttrafficpolicy.go — Quantity-to-uint32 conversion with validation, translateHostSettings
  • internal/xds/translator/listener.go — xDS translation (typed-nil safe pattern for strip_port_mode oneof, standalone bool for strip_matching_host_port)
  • CRDs regenerated, deepcopy generated
  • 3 gatewayapi golden tests (happy path, Matching mode, error for < 1Ki) + 1 xDS translator golden test (both strip modes)
  • Docs: request-header-size.md + host-port-stripping.md
  • Release notes updated

Which issue(s) this PR fixes:

Fixes #5368

Release Notes: Yes

/cc @arkodg

…cPolicy

Add maxRequestHeaderBytes to ClientTrafficPolicy.headers for configuring maximum
request header size (Envoy max_request_headers_kb). Values use resource.Quantity
format (e.g. 80Ki) and are validated to be at least 1Ki.

Add host.stripPortMode to ClientTrafficPolicy for stripping ports from the
Host/Authority header before route matching. Supports Any (unconditional) and
Matching (only when port matches listener port).

Fixes envoyproxy#5368

Signed-off-by: asalvador <asalvador@newrelic.com>
@albsga4
albsga4 requested a review from a team as a code owner April 22, 2026 23:11
@netlify

netlify Bot commented Apr 22, 2026

Copy link
Copy Markdown

Deploy Preview for cerulean-figolla-1f9435 ready!

Name Link
🔨 Latest commit f31c0f6
🔍 Latest deploy log https://app.netlify.com/projects/cerulean-figolla-1f9435/deploys/69f3c12815c3360008726d24
😎 Deploy Preview https://deploy-preview-8825--cerulean-figolla-1f9435.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 0174fe5350

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread internal/gatewayapi/clienttrafficpolicy.go
Comment thread internal/gatewayapi/clienttrafficpolicy.go
Guard against uint32 overflow by rejecting values where bytes/1024
exceeds math.MaxUint32.

Signed-off-by: asalvador <asalvador@newrelic.com>
@albsga4

albsga4 commented Apr 22, 2026

Copy link
Copy Markdown
Contributor Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 52c7f869ce

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread internal/gatewayapi/clienttrafficpolicy.go
Run docs-api-gen to include HostSettings, StripPortMode, and
MaxRequestHeaderBytes in the generated API reference.

Signed-off-by: asalvador <asalvador@newrelic.com>
albsga4 added 2 commits April 23, 2026 16:57
Add stripTrailingHostDot bool to the host section. Maps to Envoy's
strip_trailing_host_dot on the HCM. Without this, requests with
Host "example.com." don't match routes for "example.com".

Fixes envoyproxy#8832

Signed-off-by: asalvador <asalvador@newrelic.com>
Signed-off-by: asalvador <asalvador@newrelic.com>
@albsga4 albsga4 changed the title api: add maxRequestHeaderBytes and host.stripPortMode to ClientTrafficPolicy api: add maxRequestHeaderBytes and host normalization to ClientTrafficPolicy Apr 23, 2026
@codecov

codecov Bot commented Apr 30, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 90.90909% with 3 lines in your changes missing coverage. Please review.
✅ Project coverage is 74.65%. Comparing base (4628260) to head (f31c0f6).
⚠️ Report is 170 commits behind head on main.

Files with missing lines Patch % Lines
internal/gatewayapi/clienttrafficpolicy.go 86.95% 3 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #8825      +/-   ##
==========================================
+ Coverage   74.57%   74.65%   +0.07%     
==========================================
  Files         250      251       +1     
  Lines       39751    40292     +541     
==========================================
+ Hits        29644    30079     +435     
- Misses       8056     8142      +86     
- Partials     2051     2071      +20     

☔ 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.

- gocritic/ifElseChain: rewrite if-else to switch for MaxRequestHeaderBytes validation
- unparam: translateHostSettings always returned nil, remove error return

Signed-off-by: asalvador <asalvador@newrelic.com>
}

// HostSettings provides configuration options for the Host/Authority header on the listener.
type HostSettings struct {

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.

can we limit this PR to maxRequestHeaderBytes ?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Both features are HCM-level listener settings that share the same translation path in listener.gomaxRequestHeaderBytes sets the header size limit, and host normalization (StripPortMode, StripTrailingHostDot) configures how the Host/Authority header is processed before routing.

That said, they are conceptually separate — one is about size limits, the other about normalization. Happy to split into two PRs if you prefer.

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.

thanks, lets scope this PR to maxRequestHeaderBytes

// +optional
// +kubebuilder:validation:XIntOrString
// +kubebuilder:validation:Pattern="^[1-9]+[0-9]*([EPTGMK]i|[EPTGMk])?$"
MaxRequestHeaderBytes *resource.Quantity `json:"maxRequestHeaderBytes,omitempty"`

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.

based on the style of other fields in the APIs, should this be MaxRequestHeaderLimit ?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I went with MaxRequestHeaderBytes to stay close to Envoy's own field name (max_request_headers_kb) — the field represents a byte quantity via resource.Quantity (e.g. 60Ki, 1Mi), so Bytes felt natural.

I see the convention though — BufferLimit, SocketBufferLimit, ConnectionLimit all use *Limit for caps. Happy to rename to MaxRequestHeaderLimit if that's the preferred style.

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.

yeah, prefer the limit suffix instead for the user facing Envoy Gateway API, thanks

@sboulkour

Copy link
Copy Markdown
Contributor

FTR, as this PR is going to be trimmed from host settings part, I created a second PR from it #9115

sboulkour added a commit to sboulkour/gateway that referenced this pull request Jun 26, 2026
Add a new `host` section to `ClientTrafficPolicy` to normalize the
Host/Authority header on the listener, parallel to the existing `path`
section:

- `host.stripTrailingHostDot` maps to Envoy `strip_trailing_host_dot`,
  so requests with `Host: example.com.` match routes for `example.com`
  (NGINX-parity behavior).
- `host.stripPortMode` (`Any`/`Matching`) maps to Envoy
  `strip_any_host_port` / `strip_matching_host_port`.

Both were previously only achievable via fragile EnvoyPatchPolicy.

This change is split out of envoyproxy#8825 per maintainer review, which scoped
that PR to `maxRequestHeaderBytes`.

Fixes envoyproxy#8832

Co-authored-by: albsga4 <asalvador@newrelic.com>
Signed-off-by: Salim Boulkour <salim.boulkour@algolia.com>
@github-actions

Copy link
Copy Markdown
Contributor

This pull request has been automatically marked as stale because it has not had activity in the last 30 days. Please feel free to give a status update now, ping for review, when it's ready. Thank you for your contributions!

@github-actions github-actions Bot added the stale label Jun 28, 2026
@github-actions github-actions Bot closed this Jul 5, 2026
sboulkour added a commit to sboulkour/gateway that referenced this pull request Jul 8, 2026
Add a new `host` section to `ClientTrafficPolicy` to normalize the
Host/Authority header on the listener, parallel to the existing `path`
section:

- `host.stripTrailingHostDot` maps to Envoy `strip_trailing_host_dot`,
  so requests with `Host: example.com.` match routes for `example.com`
  (NGINX-parity behavior).
- `host.stripPortMode` (`Any`/`Matching`) maps to Envoy
  `strip_any_host_port` / `strip_matching_host_port`.

Both were previously only achievable via fragile EnvoyPatchPolicy.

This change is split out of envoyproxy#8825 per maintainer review, which scoped
that PR to `maxRequestHeaderBytes`.

Fixes envoyproxy#8832

Co-authored-by: albsga4 <asalvador@newrelic.com>
Signed-off-by: Salim Boulkour <salim.boulkour@algolia.com>
sboulkour added a commit to sboulkour/gateway that referenced this pull request Jul 15, 2026
Add a new `host` section to `ClientTrafficPolicy` to normalize the
Host/Authority header on the listener, parallel to the existing `path`
section:

- `host.stripTrailingHostDot` maps to Envoy `strip_trailing_host_dot`,
  so requests with `Host: example.com.` match routes for `example.com`
  (NGINX-parity behavior).
- `host.stripPortMode` (`Any`/`Matching`) maps to Envoy
  `strip_any_host_port` / `strip_matching_host_port`.

Both were previously only achievable via fragile EnvoyPatchPolicy.

This change is split out of envoyproxy#8825 per maintainer review, which scoped
that PR to `maxRequestHeaderBytes`.

Fixes envoyproxy#8832

Co-authored-by: albsga4 <asalvador@newrelic.com>
Signed-off-by: Salim Boulkour <salim.boulkour@algolia.com>
sboulkour added a commit to sboulkour/gateway that referenced this pull request Jul 15, 2026
Add a new `host` section to `ClientTrafficPolicy` to normalize the
Host/Authority header on the listener, parallel to the existing `path`
section:

- `host.stripTrailingHostDot` maps to Envoy `strip_trailing_host_dot`,
  so requests with `Host: example.com.` match routes for `example.com`
  (NGINX-parity behavior).
- `host.stripPortMode` (`Any`/`Matching`) maps to Envoy
  `strip_any_host_port` / `strip_matching_host_port`.

Both were previously only achievable via fragile EnvoyPatchPolicy.

This change is split out of envoyproxy#8825 per maintainer review, which scoped
that PR to `maxRequestHeaderBytes`.

Fixes envoyproxy#8832

Co-authored-by: albsga4 <asalvador@newrelic.com>
Signed-off-by: Salim Boulkour <salim.boulkour@algolia.com>
arkodg pushed a commit that referenced this pull request Jul 19, 2026
* feat(api): add host normalization to ClientTrafficPolicy

Add a new `host` section to `ClientTrafficPolicy` to normalize the
Host/Authority header on the listener, parallel to the existing `path`
section:

- `host.stripTrailingHostDot` maps to Envoy `strip_trailing_host_dot`,
  so requests with `Host: example.com.` match routes for `example.com`
  (NGINX-parity behavior).

Both were previously only achievable via fragile EnvoyPatchPolicy.

This change is split out of #8825 per maintainer review, which scoped
that PR to `maxRequestHeaderBytes`.

Fixes #8832

Co-authored-by: albsga4 <asalvador@newrelic.com>
Signed-off-by: Salim Boulkour <salim.boulkour@algolia.com>
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.

Add support for max request header size

3 participants