Skip to content

feat(policy-engine/controller): support host (:authority) rewrite via dynamic metadata#1609

Merged
renuka-fernando merged 10 commits intowso2:mainfrom
renuka-fernando:host-rewrite
Mar 31, 2026
Merged

feat(policy-engine/controller): support host (:authority) rewrite via dynamic metadata#1609
renuka-fernando merged 10 commits intowso2:mainfrom
renuka-fernando:host-rewrite

Conversation

@renuka-fernando
Copy link
Copy Markdown
Contributor

@renuka-fernando renuka-fernando commented Mar 31, 2026

Purpose

Fix #1598

Summary by CodeRabbit

  • New Features

    • Introduced host-rewrite policy to rewrite incoming request Host/authority before forwarding, supporting API- and operation-level configuration with overrides.
    • Request transformation now applies host/authority rewriting alongside path and method changes.
    • Policy parameter format updated to use a top-level host field for host-rewrite mappings.
  • Tests

    • Added integration tests validating host-rewrite behavior across methods and configuration layers.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Mar 31, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

Walkthrough

Adds a new host-rewrite policy and wires host mutations through the request translation pipeline (path, method, host), updates SDK policy action schema to include Host, adjusts ext_proc header mutation rules, moves policy registrations, updates several go.mod versions, and adds integration tests for host rewrite. (≤50 words)

Changes

Cohort / File(s) Summary
Policy registration & build manifests
gateway/build.yaml, gateway/build-manifest.yaml
Reordered policies and registered host-rewrite; several policy entries relocated without version changes.
New default policy
gateway/gateway-controller/default-policies/host-rewrite.yaml
Added host-rewrite policy manifest with required host parameter schema.
SDK policy schema
sdk/core/policy/v1alpha2/action.go
Added Host *string to UpstreamRequestHeaderModifications and UpstreamRequestModifications.
Policy engine kernel
gateway/gateway-runtime/policy-engine/internal/kernel/translator.go, .../translator_test.go, .../extproc.go
Introduced RequestTranslationResult and RequestMutations (now include Host); refactored translate/buildDynamicMetadata signatures and updated tests and extproc call sites.
Lua request transformation
gateway/gateway-controller/lua/request_transformation.lua
Resolve target host from metadata and rewrite :authority/Host; refactored method-rewrite control flow.
Gateway controller integration
gateway/gateway-controller/pkg/constants/constants.go, .../llm_transformer.go, .../llm_transformer_test.go, .../xds/translator.go
Switched templated policy name/params from set-headershost-rewrite; updated transformer to render host; changed ext_proc HeaderMutationRules (DisallowSystem/DisallowIsError).
Integration tests
gateway/it/features/host-rewrite.feature, gateway/it/suite_test.go
Added BDD scenarios validating operation- and API-level host rewrite behaviors; registered new feature in test suite.
Go module bumps
gateway/gateway-builder/go.mod, gateway/gateway-controller/go.mod, gateway/gateway-runtime/policy-engine/go.mod, gateway/sample-policies/.../go.mod, gateway/system-policies/analytics/go.mod
Bumped github.com/wso2/api-platform/sdk/core from v0.2.7 → v0.2.9 across modules.
Misc defaults/version bumps
gateway/gateway-controller/default-policies/model-round-robin.yaml, .../model-weighted-round-robin.yaml
Bumped default policy versions (v1.0.1 → v1.0.2).

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant Gateway
    participant PolicyEngine as Policy Engine/Translator
    participant LuaFilter as Lua Request Transformation
    participant Upstream

    Client->>Gateway: HTTP request (original Host)
    Gateway->>PolicyEngine: Translate request actions (policies)
    PolicyEngine->>PolicyEngine: Build RequestMutations{Path, Method, Host}
    PolicyEngine->>Gateway: Attach dynamic metadata (includes Host)
    Gateway->>LuaFilter: ext_proc reads dynamic metadata
    LuaFilter->>LuaFilter: resolve_target_host() -> target host
    LuaFilter->>LuaFilter: rewrite :authority and Host headers
    LuaFilter->>Upstream: Forward request (rewritten Host)
    Upstream->>Client: Response
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Suggested reviewers

  • pubudu538
  • malinthaprasan

Poem

🐰 I nibble code by moonlit light,

I hop and tuck the Host just right,
Policies now lead the way,
Upstream greets a host in play,
Hooray — proxies hop into flight! 🥕

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Description check ⚠️ Warning PR description is incomplete and fails to follow the provided template structure with required sections. Expand description to include Goals, Approach, User stories, Documentation, Automation tests (unit and integration), Security checks, Samples, Related PRs, and Test environment as specified in the template.
Docstring Coverage ⚠️ Warning Docstring coverage is 58.06% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed Title accurately summarizes the main change: adding support for host/authority rewriting via dynamic metadata in the policy engine and controller.
Linked Issues check ✅ Passed Changes comprehensively address issue #1598 by enabling host header rewriting for upstream requests, allowing vhost-based routing to function through proxies.
Out of Scope Changes check ✅ Passed All changes are directly related to implementing host rewriting functionality required by the linked issue, with no unrelated modifications detected.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
gateway/it/features/host-rewrite.feature (1)

105-133: Good test for hostRewrite: manual dependency, but scenario name could be clearer.

This scenario validates that host rewrite only works when hostRewrite: manual is configured on the upstream. The assertion should contain "echo-backend" correctly verifies the backend-derived host is preserved when manual mode is not enabled.

However, the scenario name "Host rewrite without hostRewrite manual should not work" is slightly ambiguous - it could imply the policy fails rather than that it's intentionally bypassed. Consider a clearer name like "Host rewrite policy is ignored when upstream hostRewrite is not set to manual".

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@gateway/it/features/host-rewrite.feature` around lines 105 - 133, Rename the
ambiguous scenario title to clearly state expected behavior: update the Scenario
line currently "Host rewrite without hostRewrite manual should not work" to
something like "Host rewrite policy is ignored when upstream hostRewrite is not
set to manual" in the host-rewrite.feature so the test intent is explicit; keep
the Given/When/Then steps and assertions (including the JSON assertion on
"headers.Host" containing "echo-backend") unchanged.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@gateway/it/features/host-rewrite.feature`:
- Around line 105-133: Rename the ambiguous scenario title to clearly state
expected behavior: update the Scenario line currently "Host rewrite without
hostRewrite manual should not work" to something like "Host rewrite policy is
ignored when upstream hostRewrite is not set to manual" in the
host-rewrite.feature so the test intent is explicit; keep the Given/When/Then
steps and assertions (including the JSON assertion on "headers.Host" containing
"echo-backend") unchanged.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: a33a5d51-6e03-44ab-8ea4-35f8f2b8c647

📥 Commits

Reviewing files that changed from the base of the PR and between 7e869cf and 79d6d2f.

⛔ Files ignored due to path filters (5)
  • gateway/gateway-builder/go.sum is excluded by !**/*.sum
  • gateway/gateway-controller/go.sum is excluded by !**/*.sum
  • gateway/gateway-runtime/policy-engine/go.sum is excluded by !**/*.sum
  • gateway/sample-policies/transform-payload-case/go.sum is excluded by !**/*.sum
  • gateway/system-policies/analytics/go.sum is excluded by !**/*.sum
📒 Files selected for processing (14)
  • gateway/build-manifest.yaml
  • gateway/build.yaml
  • gateway/gateway-builder/go.mod
  • gateway/gateway-controller/go.mod
  • gateway/gateway-controller/lua/request_transformation.lua
  • gateway/gateway-runtime/policy-engine/go.mod
  • gateway/gateway-runtime/policy-engine/internal/kernel/extproc.go
  • gateway/gateway-runtime/policy-engine/internal/kernel/translator.go
  • gateway/gateway-runtime/policy-engine/internal/kernel/translator_test.go
  • gateway/it/features/host-rewrite.feature
  • gateway/it/suite_test.go
  • gateway/sample-policies/transform-payload-case/go.mod
  • gateway/system-policies/analytics/go.mod
  • sdk/core/policy/v1alpha2/action.go

… dynamic metadata

- Add Host field to SDK request modification types so policies can request
  rewriting the request host/authority.
- Translator now includes host in the ext_proc dynamic metadata namespace
  (api_platform.policy_engine.envoy.filters.http.ext_proc) alongside path
  and method when policies request routing mutations.
- Refactor translateRequestActionsCore to return a result struct instead of a
  long tuple, and refactor buildDynamicMetadata to accept a RequestMutations
  struct (path/method/host) to avoid growing parameter lists.
- Update Lua request_transformation filter to read the host value from
  dynamic metadata and replace :authority and Host headers.
# Conflicts:
#	gateway/build-manifest.yaml
…er vhost

- Change PROXY_HOST__HEADER_POLICY_NAME to 'host-rewrite' and update params format
- Adjust GetHostAdditionPolicyParams to render host-rewrite params (host: value)
- Update unit test expectations to check for 'host' field instead of 'request'

When an LLM proxy is created with a provider that has a vhost configured,
the transformer now generates a host-rewrite policy to set the Host header
for upstream requests, replacing the previous set-headers policy.
Krishanx92
Krishanx92 previously approved these changes Mar 31, 2026
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
gateway/gateway-controller/lua/request_transformation.lua (1)

206-214: Harden host rewrite by validating authority format before replacement.

Line 211 and Line 212 currently accept any non-empty string. Rejecting obvious invalid forms (scheme/path/whitespace) will prevent malformed upstream authority values.

Proposed hardening diff
 local function resolve_target_host(metadata)
@@
   return nil
 end

+local function is_valid_authority(value)
+  if type(value) ~= "string" or value == "" then
+    return false
+  end
+  if string.find(value, "%s") ~= nil then
+    return false
+  end
+  if string.find(value, "://", 1, true) ~= nil then
+    return false
+  end
+  if string.find(value, "/", 1, true) ~= nil then
+    return false
+  end
+  return true
+end
+
@@
-  if target_host ~= nil and type(target_host) == "string" and target_host ~= "" then
+  if target_host ~= nil and is_valid_authority(target_host) then
     handle:logInfo("host_rewrite: target_host=" .. tostring(target_host))
     -- Replace both :authority (HTTP/2) and Host (HTTP/1) for compatibility
     handle:headers():replace(":authority", target_host)
     handle:headers():replace("host", target_host)
+  elseif target_host ~= nil then
+    handle:logWarn("host_rewrite: invalid target_host ignored")
   end
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@gateway/gateway-controller/lua/request_transformation.lua` around lines 206 -
214, The host-rewrite currently replaces :authority/host with any non-empty
string from resolve_target_host; tighten validation by verifying target_host is
a valid authority (e.g. non-empty string, does not contain "://", does not start
with "/", contains no whitespace) before calling
handle:headers():replace(":authority", target_host) and replace("host",
target_host); if validation fails, log a warning via
handle:logInfo/handle:logWarn and skip the replacement. Reference target_host,
resolve_target_host, and the handle:headers():replace calls when adding the
checks.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@gateway/gateway-controller/lua/request_transformation.lua`:
- Around line 206-214: The host-rewrite currently replaces :authority/host with
any non-empty string from resolve_target_host; tighten validation by verifying
target_host is a valid authority (e.g. non-empty string, does not contain "://",
does not start with "/", contains no whitespace) before calling
handle:headers():replace(":authority", target_host) and replace("host",
target_host); if validation fails, log a warning via
handle:logInfo/handle:logWarn and skip the replacement. Reference target_host,
resolve_target_host, and the handle:headers():replace calls when adding the
checks.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 9f13d9e8-4455-437f-abe3-dcd056c44ee2

📥 Commits

Reviewing files that changed from the base of the PR and between 467acd0 and 493466b.

⛔ Files ignored due to path filters (5)
  • gateway/gateway-builder/go.sum is excluded by !**/*.sum
  • gateway/gateway-controller/go.sum is excluded by !**/*.sum
  • gateway/gateway-runtime/policy-engine/go.sum is excluded by !**/*.sum
  • gateway/sample-policies/transform-payload-case/go.sum is excluded by !**/*.sum
  • gateway/system-policies/analytics/go.sum is excluded by !**/*.sum
📒 Files selected for processing (21)
  • gateway/build-manifest.yaml
  • gateway/build.yaml
  • gateway/gateway-builder/go.mod
  • gateway/gateway-controller/default-policies/host-rewrite.yaml
  • gateway/gateway-controller/default-policies/model-round-robin.yaml
  • gateway/gateway-controller/default-policies/model-weighted-round-robin.yaml
  • gateway/gateway-controller/go.mod
  • gateway/gateway-controller/lua/request_transformation.lua
  • gateway/gateway-controller/pkg/constants/constants.go
  • gateway/gateway-controller/pkg/utils/llm_transformer.go
  • gateway/gateway-controller/pkg/utils/llm_transformer_test.go
  • gateway/gateway-controller/pkg/xds/translator.go
  • gateway/gateway-runtime/policy-engine/go.mod
  • gateway/gateway-runtime/policy-engine/internal/kernel/extproc.go
  • gateway/gateway-runtime/policy-engine/internal/kernel/translator.go
  • gateway/gateway-runtime/policy-engine/internal/kernel/translator_test.go
  • gateway/it/features/host-rewrite.feature
  • gateway/it/suite_test.go
  • gateway/sample-policies/transform-payload-case/go.mod
  • gateway/system-policies/analytics/go.mod
  • sdk/core/policy/v1alpha2/action.go
✅ Files skipped from review due to trivial changes (11)
  • gateway/gateway-controller/default-policies/model-round-robin.yaml
  • gateway/system-policies/analytics/go.mod
  • gateway/sample-policies/transform-payload-case/go.mod
  • gateway/gateway-builder/go.mod
  • gateway/gateway-runtime/policy-engine/go.mod
  • gateway/it/suite_test.go
  • gateway/gateway-controller/go.mod
  • gateway/gateway-controller/default-policies/model-weighted-round-robin.yaml
  • gateway/gateway-runtime/policy-engine/internal/kernel/translator_test.go
  • gateway/it/features/host-rewrite.feature
  • gateway/build-manifest.yaml
🚧 Files skipped from review as they are similar to previous changes (6)
  • gateway/gateway-runtime/policy-engine/internal/kernel/extproc.go
  • gateway/gateway-controller/pkg/utils/llm_transformer.go
  • gateway/gateway-controller/pkg/constants/constants.go
  • gateway/gateway-controller/default-policies/host-rewrite.yaml
  • gateway/gateway-runtime/policy-engine/internal/kernel/translator.go
  • gateway/build.yaml

@renuka-fernando renuka-fernando merged commit 1f25670 into wso2:main Mar 31, 2026
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: Cannot access LLM Provider through proxy if provider has a vhost configured

2 participants