Skip to content

fix: route openapi playground's ?url= proxy calls to the daemon#14

Merged
BunsDev merged 1 commit into
mainfrom
fix/openapi-proxy-playground-route
May 24, 2026
Merged

fix: route openapi playground's ?url= proxy calls to the daemon#14
BunsDev merged 1 commit into
mainfrom
fix/openapi-proxy-playground-route

Conversation

@BunsDev
Copy link
Copy Markdown
Member

@BunsDev BunsDev commented May 24, 2026

Summary

After #12 landed, the Try It panels on every endpoint page rendered a Next.js 404 HTML dump instead of the daemon's JSON response. Root cause: fumadocs-openapi's playground proxies via a single endpoint with the target URL as a query parameter —

GET /api/coven-proxy?url=<encoded>&cookie=

— but #12 only shipped app/api/coven-proxy/[...path]/route.ts, a catch-all that requires at least one path segment. The playground's request hit Next's /_not-found.

Fix

  • app/api/coven-proxy/route.ts (new) — sibling route handling the ?url= style. Validates the target URL is under /api/coven-proxy/, strips that prefix, and forwards the remaining daemon-side path to the Unix socket.
  • lib/coven-proxy-dial.ts (new) — extracts the dialing logic (socket-path resolution, http.request({ socketPath }) plumbing, daemon_unreachable envelope on ENOENT / ECONNREFUSED / ETIMEDOUT / EACCES, VERCEL=1 hosted short-circuit) so both routes share one implementation.
  • app/api/coven-proxy/[...path]/route.ts — refactored to delegate to dialDaemon(). Status banner + curl tests continue to work unchanged.

Both proxy shapes end up calling dialDaemon(targetPath, method, headers, body) on $COVEN_HOME/coven.sock with the same envelope-error contract.

Test plan

  • npm run dev, start a daemon (coven daemon start), then:
    • Reload /docs/openapi/meta/get-health and click Try It → real {"ok":true,"apiVersion":"coven.daemon.v1",...} response (not a 404 HTML dump).
    • Try It on /docs/openapi/sessions/create-session with a valid body launches a real session and returns the SessionRecord.
  • Daemon status banner on /docs/openapi still flips green when a daemon is running (path-prefix route unchanged).
  • curl http://localhost:3000/api/coven-proxy/api/v1/health (path-prefix) returns the same payload as curl 'http://localhost:3000/api/coven-proxy?url=http%3A%2F%2Flocalhost%3A3000%2Fapi%2Fcoven-proxy%2Fapi%2Fv1%2Fhealth&cookie=' (playground style).
  • With no daemon, both proxy shapes return the same daemon_unreachable 503 envelope.
  • Hosted simulation: VERCEL=1 npm run dev → banner shows hosted panel; Try It returns details.hosted: true envelope.

🤖 Generated with Claude Code

The fumadocs-openapi Try It playground calls the proxy as

  /api/coven-proxy?url=<encoded-target>&cookie=

with the target URL as a query parameter — a single endpoint, not a path
prefix. The existing catch-all route at /api/coven-proxy/[...path]/route.ts
requires at least one path segment, so the playground's request hit Next's
/_not-found and the Try It panel rendered a 404 HTML dump instead of the
daemon's JSON envelope.

Adds a sibling route at /api/coven-proxy/route.ts that reads ?url=, strips
the /api/coven-proxy prefix from the target's pathname, and forwards the
remaining daemon path to the Unix socket. Extracts the dialing logic into
lib/coven-proxy-dial.ts so both proxy shapes share one implementation:

  - /api/coven-proxy/[...path]/route.ts → status banner, curl tests
  - /api/coven-proxy/route.ts           → fumadocs-openapi playground

Both end up calling dialDaemon(targetPath, ...) on $COVEN_HOME/coven.sock
with the same envelope-error contract (daemon_unreachable, invalid_request,
internal_error).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings May 24, 2026 19:31
@vercel
Copy link
Copy Markdown

vercel Bot commented May 24, 2026

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

Project Deployment Actions Updated (UTC)
coven-docs Ready Ready Preview May 24, 2026 7:31pm

@BunsDev BunsDev merged commit c80e874 into main May 24, 2026
2 checks passed
@BunsDev BunsDev deleted the fix/openapi-proxy-playground-route branch May 24, 2026 19:33
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Fixes fumadocs-openapi “Try It” requests that proxy via /api/coven-proxy?url=... by adding a sibling route handler and extracting shared Unix-socket dialing logic so both proxy shapes return consistent daemon responses/envelopes.

Changes:

  • Added /api/coven-proxy route to handle the playground’s ?url= proxy format and forward to the daemon.
  • Introduced lib/coven-proxy-dial.ts to centralize socket-path resolution, request forwarding, and daemon_unreachable error envelopes.
  • Refactored the existing catch-all /api/coven-proxy/[...path] route to delegate to the shared dialer.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.

File Description
lib/coven-proxy-dial.ts New shared helper to dial the daemon over $COVEN_HOME/coven.sock and normalize errors into consistent envelopes.
app/api/coven-proxy/route.ts New handler for fumadocs-openapi’s ?url= proxy requests; extracts daemon path and forwards via dialDaemon().
app/api/coven-proxy/[...path]/route.ts Simplified existing path-prefix proxy route by delegating socket logic to dialDaemon().

Comment on lines +46 to +54
if (!targetUrl.pathname.startsWith(PROXY_PREFIX)) {
return envelope(
'invalid_request',
`Target URL pathname must start with ${PROXY_PREFIX}: ${targetUrl.pathname}`,
{ source: 'playground' },
400,
);
}
const targetPath = targetUrl.pathname.slice(PROXY_PREFIX.length) + targetUrl.search;
Comment thread lib/coven-proxy-dial.ts
Comment on lines +90 to +103
/**
* Dial the daemon's Unix socket with the given path/method/body and return
* a `Response` mirroring the daemon's reply. On connect failure or timeout,
* returns a 503 `daemon_unreachable` envelope.
*
* `targetPath` is the daemon-side path (e.g., `/api/v1/health`), NOT the
* docs-site bridge path.
*/
export async function dialDaemon(
targetPath: string,
method: string,
requestHeaders: Headers,
body: Buffer | undefined,
): Promise<Response> {
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.

2 participants