Skip to content

fix(gateway): resolve vhost sentinel on the REST API update path#2178

Draft
mehara-rothila wants to merge 1 commit into
wso2:feature/operation-level-epfrom
mehara-rothila:fix/resolve-vhost-on-update
Draft

fix(gateway): resolve vhost sentinel on the REST API update path#2178
mehara-rothila wants to merge 1 commit into
wso2:feature/operation-level-epfrom
mehara-rothila:fix/resolve-vhost-on-update

Conversation

@mehara-rothila

@mehara-rothila mehara-rothila commented Jun 12, 2026

Copy link
Copy Markdown
Contributor

Purpose

The REST API update (PUT) path did not resolve the gateway-default vhost sentinel (_gateway_default_) before persisting and rendering. The create path already resolves and stores the concrete hostname; the update path stored the raw sentinel.

Because the xDS route builders use the stored vhost value literally (they fall back to the router default only for blank values, not the sentinel), an updated API ended up with the literal string _gateway_default_ as its vhost and became unreachable (404). The update itself returned success, so the failure was silent until traffic was tested.

Fixes #2174.

Goals

Make the update path resolve the gateway-default vhost sentinel and persist the concrete hostname, exactly as the create path does, so editing an API that uses the gateway default does not silently break its routing. A redeploy then refreshes the vhost to the current default: an API on the default stays frozen until it is redeployed.

Approach

  • Export ResolveVhostSentinels from pkg/utils/api_deployment.go (a thin wrapper over the existing internal resolveVhostSentinels) so the service layer can call it.
  • Call it in RestAPIService.Update (pkg/service/restapi/service.go) before template rendering and validation, mirroring the create path, and re-sync SourceConfiguration so the resolved value is what gets persisted.
  • No change to the resolver logic itself; the update path now reuses the same resolution the create path already performs.

User stories

As an API developer, when I edit an API that was deployed using the gateway default vhost (for example to change a backend URL), the API should keep serving on its resolved hostname instead of silently dropping off its address.

Documentation

N/A. This is a bug fix with no change to the user-facing API contract or configuration.

Automation tests

  • Unit tests

    Two handler-level tests cover the update path: TestUpdateRestAPIResolvesVhostSentinels (a PUT with a sentinel vhost persists the resolved host) and TestUpdateRestAPIPopulatesOmittedVhosts (an omitted vhost is populated with the gateway defaults and persisted; this case specifically guards the SourceConfiguration re-sync, the explicit-vhost case passes via pointer aliasing even without it). The underlying resolver is already covered by existing unit tests.

  • Integration tests

    New scenario "Sentinel vhost stays resolved after an update" in gateway/it/features/vhost-routing-single.feature: deploys an API with the sentinel vhost, updates it (PUT), and asserts it still routes on the resolved host and that the literal _gateway_default_ string is not a usable host (404). This scenario fails without the fix.

Security checks

Samples

Gateway config:

router:
  vhosts:
    main:
      default: apis.acme.com

An API deployed with the default vhost, then updated (the platform sends the marker on every deploy and update):

spec:
  vhosts:
    main: _gateway_default_
  upstream:
    main:
      url: http://order-svc:9090

Before: after an update, vhosts.main was stored as the literal _gateway_default_ and the API returned 404. After: the update resolves it to apis.acme.com and the API keeps serving.

Notes

  • The PUT response now echoes the resolved vhost values rather than the sentinel the client sent. This is consistent with the create path.
  • This change does not add write-path validation for identical main and sandbox vhosts. If both resolve to the same host, the deploy still returns 200 and the collision is only caught at xDS build time. That write-path rejection is a separate concern and applies once this fix lands on a branch that carries it. Create behaves the same way today, so this is not a regression.
  • Rows that were already persisted with the unresolved sentinel by the previous (buggy) update path are not repaired on upgrade. They resolve on the next deploy/update of that API (the platform re-sends the full spec on every reconcile). Such an API was already unreachable before the upgrade, so this introduces no new breakage.

Related PRs

N/A.

Test environment

  • Go (version per gateway/gateway-controller/go.mod)
  • Unit tests pass; integration scenario added to the vhost-routing-single suite.

@mehara-rothila

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jun 12, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai

coderabbitai Bot commented Jun 12, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Warning

Review limit reached

@mehara-rothila, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 58 minutes and 42 seconds. Learn how PR review limits work.

Your organization has run out of usage credits. Purchase more credits in the billing tab to continue.

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: bf453478-5a60-4843-9fb7-34be24096e65

📥 Commits

Reviewing files that changed from the base of the PR and between 621025f and 9f457ff.

📒 Files selected for processing (4)
  • gateway/gateway-controller/pkg/api/handlers/handlers_test.go
  • gateway/gateway-controller/pkg/service/restapi/service.go
  • gateway/gateway-controller/pkg/utils/api_deployment.go
  • gateway/it/features/vhost-routing-single.feature
📝 Walkthrough

Walkthrough

This PR fixes a bug where REST API updates do not resolve vhost sentinels (such as _gateway_default_) before persisting the configuration. The create path already performs this resolution, but the update path was storing the raw sentinel, causing the xDS builders to treat it as a literal hostname. The fix exposes the existing resolveVhostSentinels utility function, integrates it into the REST API update handler to resolve vhosts before validation, and adds an integration test that deploys an API with sentinel vhosts, updates it with a new upstream URL, and verifies that routing to the resolved hostname still functions correctly.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 66.67% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately and concisely describes the primary change: resolving vhost sentinels during REST API updates, which directly addresses the fix outlined in the PR objectives.
Linked Issues check ✅ Passed The PR directly addresses issue #2174 by implementing the suggested fix: exporting ResolveVhostSentinels, calling it in RestAPIService.Update before rendering/validation, and adding integration tests to verify vhost sentinel resolution persists through updates.
Out of Scope Changes check ✅ Passed All changes are scoped to resolving vhost sentinels on the update path: exporting a wrapper function, integrating it into the update flow, and adding corresponding tests. No unrelated modifications are present.
Description check ✅ Passed The pull request description comprehensively addresses all required template sections with detailed context, goals, approach, tests, security confirmation, and related issue references.

✏️ 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.

@coderabbitai coderabbitai Bot 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.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@gateway/it/features/vhost-routing-single.feature`:
- Around line 205-244: Add a new post-update check that targets the sandbox
vhost and asserts the sandbox upstream changed: after the existing update of
"vhost-single-sentinel-update-v1.0" and the main-host checks, add steps that
clear headers, set the request host to the sandbox vhost (the resolved host used
by the API, same resolved host used for sandbox traffic), send a GET to
"http://localhost:8080/vhost-single-sentinel-update/v1.0/whoami" and assert the
response is successful, valid JSON, and that the JSON response field "path"
equals "/sandbox-v2/whoami" to prove the sandbox route was updated.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 77378254-c16a-402a-a0ca-baf7d781d68d

📥 Commits

Reviewing files that changed from the base of the PR and between 5a8ef1e and b1909be.

📒 Files selected for processing (3)
  • gateway/gateway-controller/pkg/service/restapi/service.go
  • gateway/gateway-controller/pkg/utils/api_deployment.go
  • gateway/it/features/vhost-routing-single.feature

Comment thread gateway/it/features/vhost-routing-single.feature Outdated
@mehara-rothila mehara-rothila changed the base branch from main to feature/operation-level-ep June 12, 2026 13:38
@mehara-rothila mehara-rothila force-pushed the fix/resolve-vhost-on-update branch 2 times, most recently from f6de19d to f609e38 Compare June 12, 2026 19:23
@mehara-rothila

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jun 12, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai coderabbitai Bot 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.

♻️ Duplicate comments (1)
gateway/it/features/vhost-routing-single.feature (1)

237-249: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Add sandbox-host verification after the update.

The scenario verifies that the main vhost route still works after the update (lines 237-243) and that the sentinel literal is rejected (lines 245-249), but it does not verify that the sandbox vhost route still works after the update. Since the update includes sandbox: _gateway_default_, the scenario should also assert that the sandbox route resolves correctly after the update.

📋 Suggested addition

After line 243, add a sandbox-host check similar to the main-host check:

     When I clear all headers
     And I set request host to "api.wso2.com"
     And I send a GET request to "http://localhost:8080/vhost-single-sentinel-update/v1.0/whoami"
     Then the response should be successful
     And the response should be valid JSON
     And the JSON response field "path" should be "/whoami"

+    # Verify sandbox route also works after update
+    When I clear all headers
+    And I set request host to "api-sandbox.wso2.com"
+    And I send a GET request to "http://localhost:8080/vhost-single-sentinel-update/v1.0/whoami"
+    Then the response should be successful
+    And the response should be valid JSON
+    And the JSON response field "environment" should be "sandbox"
+    And the JSON response field "path" should be "/sandbox/whoami"
+
     # The sentinel string itself must NOT be a usable host after the update
     When I clear all headers
     And I set request host to "_gateway_default_"
     And I send a GET request to "http://localhost:8080/vhost-single-sentinel-update/v1.0/after-update"
     Then the response status code should be 404
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@gateway/it/features/vhost-routing-single.feature` around lines 237 - 249, Add
a sandbox-host verification after the existing main-host check: mirror the block
that uses the route "vhost-single-sentinel-update" and the step "And I set
request host to ..." by clearing headers, setting the request host to the
sandbox host that should resolve to _gateway_default_ (the same resolved sandbox
host used elsewhere in the feature), sending a GET to
"http://localhost:8080/vhost-single-sentinel-update/v1.0/whoami", and asserting
the response is successful, valid JSON, and that the JSON "path" equals
"/whoami".
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Duplicate comments:
In `@gateway/it/features/vhost-routing-single.feature`:
- Around line 237-249: Add a sandbox-host verification after the existing
main-host check: mirror the block that uses the route
"vhost-single-sentinel-update" and the step "And I set request host to ..." by
clearing headers, setting the request host to the sandbox host that should
resolve to _gateway_default_ (the same resolved sandbox host used elsewhere in
the feature), sending a GET to
"http://localhost:8080/vhost-single-sentinel-update/v1.0/whoami", and asserting
the response is successful, valid JSON, and that the JSON "path" equals
"/whoami".

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: b6375870-1bc8-44d6-b4bc-ef1eee5be68d

📥 Commits

Reviewing files that changed from the base of the PR and between b1909be and f609e38.

📒 Files selected for processing (4)
  • gateway/gateway-controller/pkg/api/handlers/handlers_test.go
  • gateway/gateway-controller/pkg/service/restapi/service.go
  • gateway/gateway-controller/pkg/utils/api_deployment.go
  • gateway/it/features/vhost-routing-single.feature
🚧 Files skipped from review as they are similar to previous changes (2)
  • gateway/gateway-controller/pkg/utils/api_deployment.go
  • gateway/gateway-controller/pkg/service/restapi/service.go

The update path rendered and validated without resolving the gateway-default vhost sentinel, so an updated API stored the raw marker and became unreachable. Resolve on update, mirroring the create path.

Fixes wso2#2174
@mehara-rothila mehara-rothila force-pushed the fix/resolve-vhost-on-update branch from f609e38 to 9f457ff Compare June 13, 2026 01:02
@mehara-rothila

Copy link
Copy Markdown
Contributor Author

@coderabbitai full review

@coderabbitai

coderabbitai Bot commented Jun 13, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Full review finished.

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]: REST API update does not resolve the vhost sentinel

1 participant