Skip to content

feat: swagger viewer - #90

Merged
AlyaEngineer merged 14 commits into
developfrom
feature/4-swagger-viewer
Jul 13, 2026
Merged

feat: swagger viewer#90
AlyaEngineer merged 14 commits into
developfrom
feature/4-swagger-viewer

Conversation

@Ivan-khodorov

@Ivan-khodorov Ivan-khodorov commented Jul 13, 2026

Copy link
Copy Markdown
Collaborator

Summary

Completes Feature 4 Swagger Viewer work in one feature PR.

Closes #32
Closes #45
Closes #64
Closes #65
Closes #66
Closes #67
Closes #76
Closes #77

What Changed

  • Added endpoint list grouped by path and sorted by method.
  • Added schema metadata display from schema.info.
  • Added endpoint details:
    • method;
    • path;
    • operation id;
    • summary/description;
    • path/query/header/cookie parameters;
    • request body schema and examples;
    • response schemas, examples, and status codes.
  • Added Try-It-Out execution through /api/try-it-out.
  • Added server-side request proxy to avoid browser CORS.
  • Added request validation and SSRF protections for server-side execution.
  • Added response display:
    • status;
    • status text;
    • duration;
    • headers;
    • body.
  • Added cURL generation from the same request state used by Try-It-Out.
  • Added copy-to-clipboard for generated cURL.
  • Split the Swagger Viewer into focused components:
    • endpoint-details.tsx
    • try-it-out-panel.tsx
    • curl-command-preview.tsx
    • try-it-out-response-details.tsx
    • swagger-viewer.helpers.ts
  • Added EN/RU translations.
  • Added and updated tests.

Affected Files

  • src/app/api/try-it-out/route.ts
  • src/app/api/try-it-out/route.test.ts
  • src/components/swagger-editor/swagger-editor.tsx
  • src/components/swagger-editor/swagger-editor.test.tsx
  • src/components/swagger-viewer/swagger-viewer.tsx
  • src/components/swagger-viewer/swagger-viewer.test.tsx
  • src/components/swagger-viewer/endpoint-details.tsx
  • src/components/swagger-viewer/try-it-out-panel.tsx
  • src/components/swagger-viewer/try-it-out-panel.test.tsx
  • src/components/swagger-viewer/curl-command-preview.tsx
  • src/components/swagger-viewer/try-it-out-response-details.tsx
  • src/components/swagger-viewer/swagger-viewer.helpers.ts
  • src/utils/swagger-editor/get-swagger-endpoints.ts
  • src/utils/swagger-editor/get-swagger-endpoints.test.ts
  • src/utils/swagger-editor/get-method-color.ts
  • src/utils/swagger-editor/group-endpoints-by-path.ts
  • src/i18n/messages/en.json
  • src/i18n/messages/ru.json

Validation

  • npm test
  • npm run lint
  • npm run build
  • git diff --check
  • merge-tree origin/develop HEAD

Notes

This PR intentionally does not include request History persistence. Try-It-Out currently executes the request and displays response data in the
Viewer. Saving executed requests to History belongs to Feature 5 integration and should be wired to the History service/table separately.

Summary by CodeRabbit

  • New Features
    • Added a complete Swagger/OpenAPI viewer UI with API metadata, grouped paths, method indicators, and rich endpoint sections (parameters, request/response, examples).
    • Introduced a “Try it out” experience with request validation, safe request building, cURL preview, copy-to-clipboard, and structured response details.
    • Implemented a redirect-aware, size/timeout-limited “try-it-out” API proxy with pinned public-IP validation and detailed error codes.
  • Localization
    • Expanded English and Russian strings for viewer and “Try it out” states (execute/copy, missing fields, blocked/failed requests, timeout, empty data).
  • Tests
    • Added extensive Vitest coverage for API safety/error handling, viewer rendering/interactions, and Swagger endpoint parsing/grouping.

@vercel

vercel Bot commented Jul 13, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
swagger-editor-app Ready Ready Preview, Comment Jul 13, 2026 4:34pm

@coderabbitai

coderabbitai Bot commented Jul 13, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

The Swagger viewer now normalizes and displays detailed OpenAPI endpoints, supports parameterized request execution and cURL copying, and uses a server-side proxy with DNS pinning, redirect validation, SSRF protection, response limits, and timeout handling.

Changes

Swagger endpoint model and viewer

Layer / File(s) Summary
Endpoint normalization and grouping
src/utils/swagger-editor/..., src/utils/swagger-editor/get-swagger-endpoints.test.ts
OpenAPI and Swagger 2 documents now produce detailed endpoint models with parameters, request bodies, responses, schemas, examples, server URLs, and ordered method groups.
Endpoint viewer rendering and synchronization
src/components/swagger-editor/..., src/components/swagger-viewer/..., src/i18n/messages/*
The viewer receives API metadata, groups endpoints by path, and renders endpoint details, schemas, examples, request sections, response sections, and localized empty states.

Try-it-out request flow

Layer / File(s) Summary
Request construction and response UI
src/components/swagger-viewer/swagger-viewer.helpers.ts, src/components/swagger-viewer/try-it-out-panel.tsx, src/components/swagger-viewer/*preview.tsx, src/components/swagger-viewer/*response-details.tsx
Request inputs are converted into proxied payloads and shell-safe cURL commands; required fields are validated, requests are submitted, responses are displayed, and errors are localized.
Validated proxy API
src/app/api/try-it-out/route.ts, src/app/api/try-it-out/route.test.ts
The Node route validates URLs and methods, blocks private destinations, pins DNS resolution, validates redirects, filters headers, limits response buffering, records request history, and handles request failures and timeouts.

Estimated code review effort: 5 (Critical) | ~120 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Browser
  participant SwaggerViewer
  participant TryItOutPanel
  participant TryItOutRoute
  participant DNS
  participant Upstream
  Browser->>SwaggerViewer: select endpoint
  SwaggerViewer->>TryItOutPanel: render endpoint inputs
  TryItOutPanel->>TryItOutRoute: POST /api/try-it-out
  TryItOutRoute->>DNS: resolve public destination
  DNS-->>TryItOutRoute: pinned address
  TryItOutRoute->>Upstream: send validated request
  Upstream-->>TryItOutRoute: return response
  TryItOutRoute-->>TryItOutPanel: return status, headers, and body
  TryItOutPanel-->>Browser: render response details
Loading

Possibly related PRs

Suggested reviewers: lexarudak, yuliademir, alyaengineer

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The title is related to the PR, but it is too vague to describe the main change. Use a more specific title such as 'feat: add Swagger Viewer try-it-out and endpoint details'.
✅ Passed checks (3 passed)
Check name Status Explanation
Linked Issues check ✅ Passed The PR implements endpoint listing, details, try-it-out, cURL generation, and request history recording as required.
Out of Scope Changes check ✅ Passed The changes all support Swagger Viewer functionality and test/i18n coverage, with no unrelated feature work apparent.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature/4-swagger-viewer

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

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

Actionable comments posted: 2

🤖 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 `@src/app/api/try-it-out/route.ts`:
- Around line 265-278: Cap the response body accumulated by the chunks buffer in
the response handling flow, enforcing a maximum byte size while processing data
events. Reject or otherwise abort the response once the limit is exceeded, and
preserve the existing Buffer.concat resolution for responses within the limit.

In `@src/utils/swagger-editor/get-swagger-endpoints.ts`:
- Around line 3-45: Use the canonical SwaggerEndpoint, SwaggerEndpointParameter,
and SwaggerEndpointRequestBody types from this module throughout
endpoint-details.tsx, swagger-viewer.helpers.ts, try-it-out-panel.tsx, and
swagger-viewer.tsx. Remove the duplicate type literals in those files and import
the shared types instead, preserving existing usage and exports as needed.
🪄 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: 2722c27f-72d8-4110-851d-be85fa46b124

📥 Commits

Reviewing files that changed from the base of the PR and between 87d1003 and eb92ecf.

📒 Files selected for processing (18)
  • src/app/api/try-it-out/route.test.ts
  • src/app/api/try-it-out/route.ts
  • src/components/swagger-editor/swagger-editor.test.tsx
  • src/components/swagger-editor/swagger-editor.tsx
  • src/components/swagger-viewer/curl-command-preview.tsx
  • src/components/swagger-viewer/endpoint-details.tsx
  • src/components/swagger-viewer/swagger-viewer.helpers.ts
  • src/components/swagger-viewer/swagger-viewer.test.tsx
  • src/components/swagger-viewer/swagger-viewer.tsx
  • src/components/swagger-viewer/try-it-out-panel.test.tsx
  • src/components/swagger-viewer/try-it-out-panel.tsx
  • src/components/swagger-viewer/try-it-out-response-details.tsx
  • src/i18n/messages/en.json
  • src/i18n/messages/ru.json
  • src/utils/swagger-editor/get-method-color.ts
  • src/utils/swagger-editor/get-swagger-endpoints.test.ts
  • src/utils/swagger-editor/get-swagger-endpoints.ts
  • src/utils/swagger-editor/group-endpoints-by-path.ts

Comment thread src/app/api/try-it-out/route.ts
Comment thread src/utils/swagger-editor/get-swagger-endpoints.ts

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

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 (4)
src/app/api/try-it-out/route.ts (4)

124-129: 🔒 Security & Privacy | 🟠 Major | 🏗️ Heavy lift

Do not replay credentials and bodies across redirects.

init remains unchanged for every redirect. A cross-origin 301/302/303 can therefore forward the original Authorization, Cookie, body, and method to the redirect destination. Restrict redirects to the same origin, or rebuild the request and strip sensitive headers/body when the origin or scheme changes.

🤖 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 `@src/app/api/try-it-out/route.ts` around lines 124 - 129, Update the
redirect-following loop around currentUrl and the unchanged init so credentials,
request bodies, and methods are not replayed to a different origin or scheme.
Either reject redirects that leave the original origin, or rebuild init for such
redirects by stripping sensitive headers and the body and applying the
appropriate redirect method; preserve same-origin redirect behavior.

355-358: 🩺 Stability & Availability | 🟠 Major | 🏗️ Heavy lift

Apply the timeout to DNS resolution too.
The 15s timer starts only after lookup() returns, so a slow resolver can keep the route pending past the advertised deadline. Redirects re-enter resolvePublicAddress(), so each hop repeats the uncapped DNS wait.

🤖 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 `@src/app/api/try-it-out/route.ts` around lines 355 - 358, Update
resolvePublicAddress’s DNS lookup path so the existing 15-second deadline also
covers await lookup(hostname, { all: true, verbatim: true }). Ensure the timeout
is applied per resolution attempt, including redirect hops, while preserving the
existing address handling for literal IPs and successful DNS results.

61-83: 🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

Require auth before proxying. saveRequestHistorySafely only skips persistence for anonymous callers, so unauthenticated users can still send arbitrary outbound requests through fetchValidatedUrl. Add a session check before the fetch, and consider rate limiting/quotas too.

🤖 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 `@src/app/api/try-it-out/route.ts` around lines 61 - 83, Update POST to require
an authenticated session before calling fetchValidatedUrl, using the existing
session/authentication helper and returning the established unauthorized
response when no session exists. Place this check after payload validation and
before the outbound fetch; do not allow unauthenticated requests to reach
proxying, and leave saveRequestHistorySafely behavior unchanged.

317-328: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

Reject incomplete upstream closes. In src/app/api/try-it-out/route.ts:317-328, a response that closes before end can leave this promise pending while requestMessage.close already clears the timeout. Reject non-end closes and guard against double settlement.

🤖 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 `@src/app/api/try-it-out/route.ts` around lines 317 - 328, Update the response
promise handling around the response error/data/end listeners to track whether
it has settled, reject when the upstream response closes before the end event,
and ignore subsequent events after settlement. Preserve the existing resolved
response construction for normal end events and ensure requestMessage.close
cannot leave the promise pending.
🤖 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 `@src/app/api/try-it-out/route.ts`:
- Around line 86-94: Sanitize the endpoint before passing it to
saveRequestHistorySafely in both the success and error history-recording paths.
Update the shared URL handling around url.toString() to remove userinfo and
redact or omit query parameters containing credentials or secrets, then reuse
the sanitized endpoint for both records.
- Around line 86-94: Decouple saveRequestHistorySafely from the critical
response path in the route handler: ensure Supabase authentication and insertion
cannot delay the response by applying bounded cancellation/timeout, or
dispatching persistence through a non-critical background mechanism. Preserve
history recording when possible, and add explicit error handling for rejected
asynchronous persistence calls at the referenced history-save sites.
- Around line 379-388: Update the request_history persistence in the surrounding
try-it-out handler to capture the result of the Supabase insert and inspect its
error field. Log or otherwise handle the returned error without interrupting the
request flow, preserving history persistence as best-effort rather than relying
only on the surrounding catch.

---

Outside diff comments:
In `@src/app/api/try-it-out/route.ts`:
- Around line 124-129: Update the redirect-following loop around currentUrl and
the unchanged init so credentials, request bodies, and methods are not replayed
to a different origin or scheme. Either reject redirects that leave the original
origin, or rebuild init for such redirects by stripping sensitive headers and
the body and applying the appropriate redirect method; preserve same-origin
redirect behavior.
- Around line 355-358: Update resolvePublicAddress’s DNS lookup path so the
existing 15-second deadline also covers await lookup(hostname, { all: true,
verbatim: true }). Ensure the timeout is applied per resolution attempt,
including redirect hops, while preserving the existing address handling for
literal IPs and successful DNS results.
- Around line 61-83: Update POST to require an authenticated session before
calling fetchValidatedUrl, using the existing session/authentication helper and
returning the established unauthorized response when no session exists. Place
this check after payload validation and before the outbound fetch; do not allow
unauthenticated requests to reach proxying, and leave saveRequestHistorySafely
behavior unchanged.
- Around line 317-328: Update the response promise handling around the response
error/data/end listeners to track whether it has settled, reject when the
upstream response closes before the end event, and ignore subsequent events
after settlement. Preserve the existing resolved response construction for
normal end events and ensure requestMessage.close cannot leave the promise
pending.
🪄 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: f1d66f4a-f778-47ce-8988-e3a056276ed7

📥 Commits

Reviewing files that changed from the base of the PR and between eb92ecf and 904b46e.

📒 Files selected for processing (2)
  • src/app/api/try-it-out/route.test.ts
  • src/app/api/try-it-out/route.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/app/api/try-it-out/route.test.ts

Comment thread src/app/api/try-it-out/route.ts Outdated
Comment thread src/app/api/try-it-out/route.ts Outdated

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

🧹 Nitpick comments (4)
src/app/api/try-it-out/route.test.ts (4)

465-486: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Missing history-insertion assertion for DNS timeout.

Similar to the other new edge-case tests, this timeout test doesn't verify that mocks.insert was called with the timeout error details, unlike how earlier tests validate history recording for their respective error paths.

🤖 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 `@src/app/api/try-it-out/route.test.ts` around lines 465 - 486, Extend the
DNS-resolution timeout test around POST to assert that mocks.insert was called
with the timeout error details, matching the history-recording assertions used
by the other error-path tests. Keep the existing response status, error payload,
and httpsRequestMock assertions unchanged.

417-441: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Missing history-insertion assertion for the blocked cross-origin redirect.

The analogous private-destination blocking tests (Lines 205-247) assert mocks.insert records the blockedUrl error/details. This redirect-block test verifies request/response behavior but not that the failure was recorded to history, leaving that side effect unverified for this distinct code path (mid-flow redirect rejection vs. upfront validation).

🤖 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 `@src/app/api/try-it-out/route.test.ts` around lines 417 - 441, Add a
history-insertion assertion to the cross-origin redirect test around the POST
call, verifying mocks.insert records the blockedUrl failure and corresponding
error details, matching the analogous private-destination blocking tests while
preserving the existing request and response assertions.

317-349: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Missing history-insertion assertion for the incomplete-close failure path.

Sibling requestFailed tests (e.g., the request/response stream error cases) assert that the failure is recorded via mocks.insert. This test only checks the HTTP response, leaving the audit/history side effect for this specific incomplete-close edge case unverified.

Suggested addition
     expect(response.status).toBe(502);
     await expect(response.json()).resolves.toEqual({ errorCode: 'requestFailed' });
+    expect(mocks.insert).toHaveBeenCalledWith(
+      expect.objectContaining({ status_code: null }),
+    );
   });
🤖 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 `@src/app/api/try-it-out/route.test.ts` around lines 317 - 349, Extend the
incomplete upstream close test in “rejects incomplete upstream closes before the
end event” to assert that the requestFailed failure is recorded through
mocks.insert, matching the sibling request/response stream error tests. Verify
the inserted history entry for this specific close-before-end path while
preserving the existing 502 response assertions.

164-172: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Repeated request-construction boilerplate across the suite.

The new Request('http://localhost/api/try-it-out', { body: JSON.stringify(...), method: 'POST' }) pattern is duplicated across most tests in this ~630-line file. Extracting a small createTryItOutRequest(payload) helper would reduce duplication and improve readability without changing behavior.

🤖 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 `@src/app/api/try-it-out/route.test.ts` around lines 164 - 172, Extract the
repeated POST Request construction in the try-it-out test suite into a
createTryItOutRequest(payload) helper, then update the affected POST calls to
use it while preserving each payload and existing test behavior.
🤖 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.

Nitpick comments:
In `@src/app/api/try-it-out/route.test.ts`:
- Around line 465-486: Extend the DNS-resolution timeout test around POST to
assert that mocks.insert was called with the timeout error details, matching the
history-recording assertions used by the other error-path tests. Keep the
existing response status, error payload, and httpsRequestMock assertions
unchanged.
- Around line 417-441: Add a history-insertion assertion to the cross-origin
redirect test around the POST call, verifying mocks.insert records the
blockedUrl failure and corresponding error details, matching the analogous
private-destination blocking tests while preserving the existing request and
response assertions.
- Around line 317-349: Extend the incomplete upstream close test in “rejects
incomplete upstream closes before the end event” to assert that the
requestFailed failure is recorded through mocks.insert, matching the sibling
request/response stream error tests. Verify the inserted history entry for this
specific close-before-end path while preserving the existing 502 response
assertions.
- Around line 164-172: Extract the repeated POST Request construction in the
try-it-out test suite into a createTryItOutRequest(payload) helper, then update
the affected POST calls to use it while preserving each payload and existing
test behavior.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 1813009b-3db1-48e0-bb63-ff357860138c

📥 Commits

Reviewing files that changed from the base of the PR and between 5a6034b and be43aed.

📒 Files selected for processing (2)
  • src/app/api/try-it-out/route.test.ts
  • src/app/api/try-it-out/route.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/app/api/try-it-out/route.ts

@AlyaEngineer AlyaEngineer changed the title Feature/4 swagger viewer feat: swagger viewer Jul 13, 2026
@AlyaEngineer
AlyaEngineer merged commit 73b26bd into develop Jul 13, 2026
3 checks passed
@coderabbitai coderabbitai Bot mentioned this pull request Jul 13, 2026
8 tasks
@coderabbitai coderabbitai Bot mentioned this pull request Jul 14, 2026
8 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

3 participants