Skip to content

[Devportal] Fix the tryout functionality using a proxy - #2818

Merged
lasanthaS merged 5 commits into
wso2:mainfrom
Piumal1999:tryout-proxy
Jul 23, 2026
Merged

[Devportal] Fix the tryout functionality using a proxy#2818
lasanthaS merged 5 commits into
wso2:mainfrom
Piumal1999:tryout-proxy

Conversation

@Piumal1999

Copy link
Copy Markdown
Contributor

Purpose

Fix #2610

Goals

Fixing the tryout

Approach

Added a proxy for invoking the APIs
Passed the proxy url to the elements-ui, so the APIs invoked through the devportal UI will go through the proxy and give the responses.
In the UI, it will show the real url as usual.

Additionally some of the redundant samples were removed.

@coderabbitai

coderabbitai Bot commented Jul 23, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Warning

Review limit reached

@Piumal1999, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 42 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

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.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 398ece9e-39ec-4696-8f3a-3917725dc11a

📥 Commits

Reviewing files that changed from the base of the PR and between 8ac4005 and 5df432f.

📒 Files selected for processing (4)
  • portals/developer-portal/src/routes/pages/tryoutProxyRoute.js
  • portals/developer-portal/src/utils/sampleApiLoader.js
  • portals/developer-portal/src/utils/ssrfGuard.js
  • portals/developer-portal/src/utils/ssrfGuard.test.js
📝 Walkthrough

Walkthrough

The developer portal adds a configurable server-side Try It proxy with same-site checks, endpoint allowlisting, header filtering, and SSRF protection. Existing sample API documentation is replaced with a Reading-List-API CRUD example, and YAML definition discovery is expanded.

Changes

Try It proxy

Layer / File(s) Summary
Tryout configuration and UI wiring
portals/developer-portal/configs/config-template.toml, portals/developer-portal/src/config/configDefaults.js, portals/developer-portal/src/controllers/apiContentController.js, portals/developer-portal/src/pages/partials/api-specification.hbs, portals/developer-portal/src/app.js
Adds Tryout settings, mounts the proxy after authentication middleware, and passes an absolute proxy URL to the API documentation component.
Allowlisting and SSRF protection
portals/developer-portal/src/services/tryoutProxyService.js, portals/developer-portal/src/utils/ssrfGuard.js, portals/developer-portal/package.json
Resolves registered endpoints, validates schemes, hosts, ports, paths, credentials, headers, and DNS destinations, then performs bounded outbound requests.
Proxy request handling
portals/developer-portal/src/routes/pages/tryoutProxyRoute.js, portals/developer-portal/src/controllers/tryoutProxyController.js, portals/developer-portal/src/middlewares/ensureAuthenticated.js
Preserves raw request bodies and enforces portal-mode, authentication, same-site, API-type, target, response, and error-handling rules.
SSRF regression coverage
portals/developer-portal/src/utils/ssrfGuard.test.js
Tests IP, DNS, private-range, metadata-range, mapped-address, multi-candidate, and scheme validation behavior.

Reading List sample APIs

Layer / File(s) Summary
Reading List API contract
portals/developer-portal/samples/apis/reading-list-api-v1.0/*
Adds the Reading-List-API manifest, OpenAPI contract, book schemas, CRUD endpoints, and overview documentation.
Sample publishing documentation
portals/developer-portal/README.md, portals/developer-portal/docs/introduction/quick-start.md, portals/developer-portal/docs/administer/design-mode.md, portals/developer-portal/src/pages/settings/partials/cfg-apis-panel.hbs
Updates publishing instructions, catalog examples, directory examples, and wizard placeholders to use Reading-List-API.
Sample definition discovery
portals/developer-portal/src/utils/sampleApiLoader.js
Adds definition.yaml to the definition filename candidates.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant APIUser
  participant DeveloperPortal
  participant tryoutProxyController
  participant tryoutProxyService
  participant RegisteredAPI
  APIUser->>DeveloperPortal: Open API documentation
  DeveloperPortal->>APIUser: Render Try It with portal proxy
  APIUser->>tryoutProxyController: Submit Try It request
  tryoutProxyController->>tryoutProxyService: Validate and proxy request
  tryoutProxyService->>RegisteredAPI: Forward allowed request
  RegisteredAPI-->>tryoutProxyService: Return response
  tryoutProxyService-->>tryoutProxyController: Return filtered response
  tryoutProxyController-->>APIUser: Return status, headers, and body
Loading

Suggested reviewers: renuka-fernando, krishanx92, lasanthas, virajsalaka, thushani-jayasekera

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Description check ⚠️ Warning The description only covers Purpose, Goals, and Approach, missing most required template sections. Add the missing sections: User stories, Documentation, Automation tests, Security checks, Samples, Related PRs, and Test environment.
Docstring Coverage ⚠️ Warning Docstring coverage is 64.00% 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 The title clearly states the main change: fixing Devportal tryout via a proxy.
Linked Issues check ✅ Passed The proxy-based tryout fix and UI routing changes address the CORS-blocked Devportal tryout issue in #2610.
Out of Scope Changes check ✅ Passed The remaining changes are supporting proxy, security, test, and sample updates and do not appear unrelated to the tryout fix.
✨ 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.

@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: 5

🧹 Nitpick comments (1)
portals/developer-portal/src/utils/ssrfGuard.js (1)

63-132: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick win

Add regression coverage for the SSRF guard, including IPv4-mapped IPv6 loopback and private addresses.

The guard is implemented, but there are no existing test/spec references covering isDenied, createGuardedLookup, or Happy Eyeballs [all: true] behavior, and the project’s test scripts are absent.

🤖 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 `@portals/developer-portal/src/utils/ssrfGuard.js` around lines 63 - 132, Add
regression tests for the SSRF guard covering isDenied with IPv4-mapped IPv6
loopback and private addresses, including allowPrivate behavior, and
createGuardedLookup rejection of denied destinations. Also cover the dns.lookup
callback path with options.all true, verifying every resolved candidate is
checked and denied candidates produce an error. Use the repository’s existing
test conventions or add an appropriate test script if none exists.

Source: Coding guidelines

🤖 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
`@portals/developer-portal/samples/apis/reading-list-api-v1.0/docs/overview.md`:
- Around line 51-54: Replace the hardcoded admin:admin authorization value in
the REST API registration curl example with environment-variable credentials
such as GATEWAY_USER and GATEWAY_PASSWORD, and explicitly mark any documented
default credentials as local-only.

In `@portals/developer-portal/src/config/configDefaults.js`:
- Around line 179-197: Set DEFAULTS.tryout.allowPrivateEndpoints to false so
private-endpoint access is disabled by default. Also update
portals/developer-portal/configs/config-template.toml lines 207-214 to set
allow_private_endpoints to false and revise its inline comment to describe
explicit operator opt-in.

In `@portals/developer-portal/src/controllers/tryoutProxyController.js`:
- Around line 49-61: Update isSameSiteRequest to fail closed when both
sec-fetch-site and Origin are absent: return false instead of treating the
request as an allowed non-browser caller. Preserve the existing same-site Fetch
Metadata and Origin host validation behavior.
- Around line 63-92: Update proxyTryoutRequest to perform the same
authentication, visibility, subscription, and organization-membership
authorization used by the corresponding documentation/page routes before calling
tryoutProxyService.proxyTryout. Resolve the organization UUID and validate
access to the requested orgName, apiHandle, apiType, and view context before
relaying any target request, while preserving the existing early config, origin,
type, and target validation responses.

In `@portals/developer-portal/src/routes/pages/tryoutProxyRoute.js`:
- Around line 29-36: Handle errors from the express.raw middleware locally in
the tryout-proxy router before they reach the global error handler. Add
router-level error handling around the middleware and return the controller’s
JSON error shape for body-size violations, using HTTP 413 and a generic message;
preserve byte-for-byte parsing and normal delegation to
tryoutProxyController.proxyTryoutRequest.

---

Nitpick comments:
In `@portals/developer-portal/src/utils/ssrfGuard.js`:
- Around line 63-132: Add regression tests for the SSRF guard covering isDenied
with IPv4-mapped IPv6 loopback and private addresses, including allowPrivate
behavior, and createGuardedLookup rejection of denied destinations. Also cover
the dns.lookup callback path with options.all true, verifying every resolved
candidate is checked and denied candidates produce an error. Use the
repository’s existing test conventions or add an appropriate test script if none
exists.
🪄 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: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 0e6f03ca-0497-401d-9298-de314e188ec4

📥 Commits

Reviewing files that changed from the base of the PR and between 571e7f2 and 4f5215c.

⛔ Files ignored due to path filters (2)
  • portals/developer-portal/package-lock.json is excluded by !**/package-lock.json
  • portals/developer-portal/samples/apis/swagger-petstore-v1.0.7/web/api-icon.png is excluded by !**/*.png
📒 Files selected for processing (30)
  • portals/developer-portal/README.md
  • portals/developer-portal/configs/config-template.toml
  • portals/developer-portal/docs/administer/design-mode.md
  • portals/developer-portal/docs/introduction/quick-start.md
  • portals/developer-portal/package.json
  • portals/developer-portal/samples/apis/booking-api/api.yaml
  • portals/developer-portal/samples/apis/booking-api/definition.yaml
  • portals/developer-portal/samples/apis/booking-api/docs/overview.md
  • portals/developer-portal/samples/apis/ping-api/api.yaml
  • portals/developer-portal/samples/apis/ping-api/definition.yaml
  • portals/developer-portal/samples/apis/ping-api/docs/overview.md
  • portals/developer-portal/samples/apis/reading-list-api-v1.0/api.yaml
  • portals/developer-portal/samples/apis/reading-list-api-v1.0/definition.yml
  • portals/developer-portal/samples/apis/reading-list-api-v1.0/docs/overview.md
  • portals/developer-portal/samples/apis/swagger-petstore-v1.0.7/api.yaml
  • portals/developer-portal/samples/apis/swagger-petstore-v1.0.7/definition.yml
  • portals/developer-portal/samples/apis/swagger-petstore-v1.0.7/docs/FAQ/faq.md
  • portals/developer-portal/samples/apis/swagger-petstore-v1.0.7/docs/getting-started.md
  • portals/developer-portal/samples/apis/swagger-petstore-v1.0.7/docs/overview.md
  • portals/developer-portal/samples/apis/swagger-petstore-v1.0.7/web/api-content.hbs
  • portals/developer-portal/src/app.js
  • portals/developer-portal/src/config/configDefaults.js
  • portals/developer-portal/src/controllers/apiContentController.js
  • portals/developer-portal/src/controllers/tryoutProxyController.js
  • portals/developer-portal/src/pages/partials/api-specification.hbs
  • portals/developer-portal/src/pages/settings/partials/cfg-apis-panel.hbs
  • portals/developer-portal/src/routes/pages/tryoutProxyRoute.js
  • portals/developer-portal/src/services/tryoutProxyService.js
  • portals/developer-portal/src/utils/sampleApiLoader.js
  • portals/developer-portal/src/utils/ssrfGuard.js
💤 Files with no reviewable changes (12)
  • portals/developer-portal/samples/apis/booking-api/api.yaml
  • portals/developer-portal/samples/apis/swagger-petstore-v1.0.7/docs/getting-started.md
  • portals/developer-portal/samples/apis/ping-api/definition.yaml
  • portals/developer-portal/samples/apis/ping-api/docs/overview.md
  • portals/developer-portal/samples/apis/swagger-petstore-v1.0.7/docs/FAQ/faq.md
  • portals/developer-portal/samples/apis/booking-api/docs/overview.md
  • portals/developer-portal/samples/apis/swagger-petstore-v1.0.7/docs/overview.md
  • portals/developer-portal/samples/apis/ping-api/api.yaml
  • portals/developer-portal/samples/apis/swagger-petstore-v1.0.7/api.yaml
  • portals/developer-portal/samples/apis/booking-api/definition.yaml
  • portals/developer-portal/samples/apis/swagger-petstore-v1.0.7/web/api-content.hbs
  • portals/developer-portal/samples/apis/swagger-petstore-v1.0.7/definition.yml

Comment thread portals/developer-portal/samples/apis/reading-list-api-v1.0/docs/overview.md Outdated
Comment thread portals/developer-portal/src/config/configDefaults.js
Comment thread portals/developer-portal/src/controllers/tryoutProxyController.js
Comment thread portals/developer-portal/src/controllers/tryoutProxyController.js
Comment thread portals/developer-portal/src/routes/pages/tryoutProxyRoute.js
coderabbitai[bot]
coderabbitai Bot previously approved these changes Jul 23, 2026
lasanthaS
lasanthaS previously approved these changes Jul 23, 2026

@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: 3

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
portals/developer-portal/src/utils/sampleApiLoader.js (1)

41-46: 🔒 Security & Privacy | 🟡 Minor | ⚡ Quick win

Reject percent-encoded traversal sequences before resolving.

Line 42 rejects literal null bytes, but accepts raw %2e, %2f, and %5c sequences. Fail closed on encoded dot, separator, and null-byte forms as required.

Proposed fix
 function safeResolve(rootDir, ...segments) {
-    if (segments.some(s => typeof s !== 'string' || s.includes('\0'))) return null;
+    if (segments.some(s =>
+        typeof s !== 'string'
+        || s.includes('\0')
+        || /%(?:00|2e|2f|5c)/i.test(s)
+    )) return null;

As per coding guidelines, user-controlled paths must “reject traversal, null bytes, and URL-encoded traversal.”

🤖 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 `@portals/developer-portal/src/utils/sampleApiLoader.js` around lines 41 - 46,
Update safeResolve to reject percent-encoded traversal and separator sequences,
including encoded dots, forward/backslashes, and null bytes, before calling
path.resolve. Apply the validation to every segment and return null for any
matching encoding while preserving the existing literal null-byte and
root-containment checks.

Source: Coding guidelines

🤖 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
`@portals/developer-portal/samples/apis/reading-list-api-v1.0/docs/overview.md`:
- Around line 42-45: Replace the localhost value in the Production gateway URL
in the overview documentation with the deployed production hostname, and update
the corresponding productionUrl in the reading-list API definition consistently;
keep the Sandbox URL unchanged.

In `@portals/developer-portal/src/routes/pages/tryoutProxyRoute.js`:
- Around line 94-105: Update authenticateLikeSpecPage to handle
ensureAuthenticated outcomes locally: return the proxy route’s generic JSON 401
response for unauthenticated redirects and authorization errors, and do not
forward those failures to the global handler. Preserve normal next() behavior
for authenticated requests and unrelated errors.

In `@portals/developer-portal/src/utils/ssrfGuard.js`:
- Around line 59-68: Update the PRIVATE_CIDRS definition to include the legacy
IPv6 site-local range fec0::/10 so isDenied rejects fec0::1 when allowPrivate is
false. Add a regression test covering that behavior.

---

Outside diff comments:
In `@portals/developer-portal/src/utils/sampleApiLoader.js`:
- Around line 41-46: Update safeResolve to reject percent-encoded traversal and
separator sequences, including encoded dots, forward/backslashes, and null
bytes, before calling path.resolve. Apply the validation to every segment and
return null for any matching encoding while preserving the existing literal
null-byte and root-containment checks.
🪄 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: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: e80f7be8-1ef2-42dc-91b2-bf2f188049d8

📥 Commits

Reviewing files that changed from the base of the PR and between 4f5215c and 8ac4005.

⛔ Files ignored due to path filters (2)
  • portals/developer-portal/package-lock.json is excluded by !**/package-lock.json
  • portals/developer-portal/samples/apis/swagger-petstore-v1.0.7/web/api-icon.png is excluded by !**/*.png
📒 Files selected for processing (32)
  • portals/developer-portal/README.md
  • portals/developer-portal/configs/config-template.toml
  • portals/developer-portal/docs/administer/design-mode.md
  • portals/developer-portal/docs/introduction/quick-start.md
  • portals/developer-portal/package.json
  • portals/developer-portal/samples/apis/booking-api/api.yaml
  • portals/developer-portal/samples/apis/booking-api/definition.yaml
  • portals/developer-portal/samples/apis/booking-api/docs/overview.md
  • portals/developer-portal/samples/apis/ping-api/api.yaml
  • portals/developer-portal/samples/apis/ping-api/definition.yaml
  • portals/developer-portal/samples/apis/ping-api/docs/overview.md
  • portals/developer-portal/samples/apis/reading-list-api-v1.0/api.yaml
  • portals/developer-portal/samples/apis/reading-list-api-v1.0/definition.yml
  • portals/developer-portal/samples/apis/reading-list-api-v1.0/docs/overview.md
  • portals/developer-portal/samples/apis/swagger-petstore-v1.0.7/api.yaml
  • portals/developer-portal/samples/apis/swagger-petstore-v1.0.7/definition.yml
  • portals/developer-portal/samples/apis/swagger-petstore-v1.0.7/docs/FAQ/faq.md
  • portals/developer-portal/samples/apis/swagger-petstore-v1.0.7/docs/getting-started.md
  • portals/developer-portal/samples/apis/swagger-petstore-v1.0.7/docs/overview.md
  • portals/developer-portal/samples/apis/swagger-petstore-v1.0.7/web/api-content.hbs
  • portals/developer-portal/src/app.js
  • portals/developer-portal/src/config/configDefaults.js
  • portals/developer-portal/src/controllers/apiContentController.js
  • portals/developer-portal/src/controllers/tryoutProxyController.js
  • portals/developer-portal/src/middlewares/ensureAuthenticated.js
  • portals/developer-portal/src/pages/partials/api-specification.hbs
  • portals/developer-portal/src/pages/settings/partials/cfg-apis-panel.hbs
  • portals/developer-portal/src/routes/pages/tryoutProxyRoute.js
  • portals/developer-portal/src/services/tryoutProxyService.js
  • portals/developer-portal/src/utils/sampleApiLoader.js
  • portals/developer-portal/src/utils/ssrfGuard.js
  • portals/developer-portal/src/utils/ssrfGuard.test.js
💤 Files with no reviewable changes (12)
  • portals/developer-portal/samples/apis/ping-api/docs/overview.md
  • portals/developer-portal/samples/apis/booking-api/definition.yaml
  • portals/developer-portal/samples/apis/swagger-petstore-v1.0.7/docs/FAQ/faq.md
  • portals/developer-portal/samples/apis/booking-api/docs/overview.md
  • portals/developer-portal/samples/apis/swagger-petstore-v1.0.7/docs/getting-started.md
  • portals/developer-portal/samples/apis/booking-api/api.yaml
  • portals/developer-portal/samples/apis/ping-api/definition.yaml
  • portals/developer-portal/samples/apis/swagger-petstore-v1.0.7/api.yaml
  • portals/developer-portal/samples/apis/swagger-petstore-v1.0.7/docs/overview.md
  • portals/developer-portal/samples/apis/swagger-petstore-v1.0.7/web/api-content.hbs
  • portals/developer-portal/samples/apis/ping-api/api.yaml
  • portals/developer-portal/samples/apis/swagger-petstore-v1.0.7/definition.yml
🚧 Files skipped from review as they are similar to previous changes (10)
  • portals/developer-portal/src/config/configDefaults.js
  • portals/developer-portal/docs/administer/design-mode.md
  • portals/developer-portal/src/pages/partials/api-specification.hbs
  • portals/developer-portal/samples/apis/reading-list-api-v1.0/api.yaml
  • portals/developer-portal/src/pages/settings/partials/cfg-apis-panel.hbs
  • portals/developer-portal/docs/introduction/quick-start.md
  • portals/developer-portal/src/controllers/apiContentController.js
  • portals/developer-portal/configs/config-template.toml
  • portals/developer-portal/src/controllers/tryoutProxyController.js
  • portals/developer-portal/src/services/tryoutProxyService.js

Comment thread portals/developer-portal/src/routes/pages/tryoutProxyRoute.js
Comment thread portals/developer-portal/src/utils/ssrfGuard.js
@lasanthaS
lasanthaS merged commit 8953843 into wso2:main Jul 23, 2026
9 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][Devportal]: Tryout is not working due to cors issues

2 participants