Skip to content

fix(policy-engine): resolve upstream base path for dynamic routing#2000

Open
renuka-fernando wants to merge 2 commits into
wso2:mainfrom
renuka-fernando:dynamic-ep
Open

fix(policy-engine): resolve upstream base path for dynamic routing#2000
renuka-fernando wants to merge 2 commits into
wso2:mainfrom
renuka-fernando:dynamic-ep

Conversation

@renuka-fernando
Copy link
Copy Markdown
Contributor

Purpose

The dynamic-endpoint policy routes a request to a named upstreamDefinitions entry via the SDK UpstreamName field. When the targeted upstream definition had a base path (e.g. http://backend:9080/foo), the gateway switched to the correct upstream cluster but failed to apply the upstream's base path — the request reached the backend at the wrong path. This PR fixes that and adds integration coverage for the policy.

Approach

  • Fix upstreamDefinitionPaths lookup in translator.go: it was keyed by the raw upstream-definition name, but the controller keys the map by the full cluster key (upstream_<Kind>_<UUID>_<name>); look it up by the constructed cluster name so the base path is actually resolved.
  • Fix the routed path construction: replace naive string concatenation (which left the API context in the path, e.g. /foo/<context>/v1.0/items) with the existing computeUpstreamPath helper, which strips the API context before prepending the upstream base path. This also wires in a previously unused function.
  • Correct a misleading comment on RouteMetadata.UpstreamDefinitionPaths (it holds cluster keys, not names).
  • Add gateway/it/features/dynamic-endpoint.feature covering named-upstream routing, per-operation base paths, and the required targetUpstream parameter, and register it in the default IT suite.

Related Issues

Fixes #1999

Checklist

  • Tests added or updated (unit, integration, etc.)
  • Samples updated (if applicable)

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 21, 2026

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 2e71b331-6a0b-45c5-b8ec-7e38e1d287f1

📥 Commits

Reviewing files that changed from the base of the PR and between 5850937 and 29a0bc2.

📒 Files selected for processing (7)
  • gateway/gateway-controller/pkg/models/runtime_deploy_config.go
  • gateway/gateway-controller/pkg/policyxds/snapshot.go
  • gateway/gateway-controller/pkg/transform/restapi.go
  • gateway/gateway-runtime/policy-engine/internal/kernel/extproc.go
  • gateway/gateway-runtime/policy-engine/internal/kernel/translator.go
  • gateway/it/features/dynamic-endpoint.feature
  • gateway/it/suite_test.go
✅ Files skipped from review due to trivial changes (1)
  • gateway/gateway-runtime/policy-engine/internal/kernel/extproc.go

📝 Walkthrough

Changes Overview

This PR fixes dynamic-endpoint routing so named upstream definitions' base paths are applied when forwarding requests, and adds integration tests covering the behavior.

Code changes

  • translator.go

    • Lookup of upstream base paths now uses the constructed Envoy cluster key (upstream_) so the correct upstreamDefinitionPaths entry is found.
    • Replaced naive string concatenation with computeUpstreamPath(...) to strip the API context before prepending the upstream base path, producing correct forwarded paths (e.g., /foo/items).
  • extproc.go

    • Clarified comment: RouteMetadata.UpstreamDefinitionPaths contains cluster keys (not raw names) mapped to URL base paths.
  • gateway-controller model and transformers

    • Added UpstreamCluster.Name to include the upstream definition name on runtime cluster entries.
    • RestAPI transformer now sets UpstreamCluster.Name when creating clusters for upstreamDefinitions.
    • snapshot translation updated to build upstream_definition_paths keyed by the upstream definition name (when present), matching how policies resolve base paths.

Tests

  • Added integration feature gateway/it/features/dynamic-endpoint.feature with scenarios for:
    • Routing a single operation to an alternate upstream and verifying path prefix.
    • Routing multiple operations to different upstreams with different base paths.
    • Ensuring deployment fails when required targetUpstream parameter is omitted.
  • Registered the new feature in the default IT suite (gateway/it/suite_test.go).

Impact

Requests routed via the dynamic-endpoint policy to named upstream definitions now include the upstream's base path (fixes #1999). Integration tests exercise named-upstream routing, per-operation base paths, and parameter validation.

Walkthrough

This pull request fixes upstream base path handling in the dynamic-endpoint policy. The core issue involved two bugs in request translation: incorrect lookup of upstream definition paths (using raw upstream names instead of cluster keys) and improper path computation (naive concatenation that retained API context). The fix updates the translator to use cluster names for path lookup and introduces computeUpstreamPath() for correct path assembly. Documentation is clarified to reflect cluster-key-based mapping semantics. Integration tests validate correct upstream selection, base path application, and deployment validation for the policy across multiple routing scenarios.

Sequence Diagram(s)

sequenceDiagram
  participant RestAPITransformer
  participant TranslateRuntimeConfigs
  participant Gateway_PolicyEngine as PolicyEngine.TranslateRequestHeaderActions
  participant Backend

  RestAPITransformer->>TranslateRuntimeConfigs: create UpstreamCluster{Name: def.Name, BasePath, Endpoints}
  TranslateRuntimeConfigs->>PolicyEngine.TranslateRequestHeaderActions: publish upstream_definition_paths keyed by UpstreamCluster.Name
  Client->>PolicyEngine.TranslateRequestHeaderActions: HTTP request (operation with targetUpstream)
  PolicyEngine.TranslateRequestHeaderActions->>PolicyEngine.TranslateRequestHeaderActions: computeUpstreamPath(apiPath, apiContext, targetUpstreamBase)
  PolicyEngine.TranslateRequestHeaderActions->>Backend: forward request to <computed upstream base> + <operation path>
  Backend-->>Client: response
Loading
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title 'fix(policy-engine): resolve upstream base path for dynamic routing' clearly and specifically describes the main change—fixing upstream base path resolution for dynamic routing in the policy engine.
Description check ✅ Passed The PR description covers purpose, approach, related issues, and testing scope. However, it does not fully align with the template, missing sections on documentation, security checks, test environment, and samples.
Linked Issues check ✅ Passed The changes comprehensively address issue #1999 by correcting the upstreamDefinitionPaths lookup, using computeUpstreamPath to properly strip API context, updating documentation, and adding integration tests.
Out of Scope Changes check ✅ Passed All changes are directly scoped to fixing upstream base path resolution and adding integration tests. The modifications to translator.go, snapshot.go, restapi.go, extproc.go, and the new feature file are all aligned with the stated objectives.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

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

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

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 golangci-lint (2.12.2)

level=error msg="[linters_context] typechecking error: pattern ./...: directory prefix . does not contain modules listed in go.work or their selected dependencies"


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.

malinthaprasan
malinthaprasan previously approved these changes May 21, 2026
Two bugs prevented the dynamic-endpoint policy from applying a target
upstream definition's base path when routing via UpstreamName:

- The controller exposed upstream base paths keyed by an internal
  cluster key, but the policy engine looked them up by the upstream
  definition name (the policy's targetUpstream value), so the lookup
  always missed and the base path defaulted to "/". Key the map by
  definition name in the controller so both sides agree, and add a
  Name field to UpstreamCluster to carry it.
- Even once resolved, the routed path was built by naive concatenation
  that left the API context in place (e.g. /foo/ctx/v1/items). Use
  computeUpstreamPath to strip the context before prepending the
  upstream base path.

Add gateway integration test features/dynamic-endpoint.feature covering
named-upstream routing, per-operation base paths, and the required
targetUpstream parameter, and register it in the default suite.
Add a root-upstream definition with no URL path to the per-operation
routing scenario, exercising the basePath="/" default in the controller
and the empty-base-path branch of computeUpstreamPath in the policy
engine, which strips the API context but prepends nothing.
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.

Dynamic Endpoint policy does not apply upstream base path

2 participants