Skip to content

Add CORS support for direct cross-origin browser clients #32

Description

@Atharva0506

Problem

The relay serves no CORS headers at all — confirmed via `grep -rn "cors|CORS|Access-Control"` across the Go source, which returns nothing, and there's no middleware registered for it in `cmd/relay/main.go`'s handler chain (`API Key → Rate Limiter → Router`).

Any browser-based consumer that calls the relay directly (i.e. without routing through a same-origin reverse proxy) hits a blocked preflight:

```
Access to fetch at 'https://thrubox-server.onrender.com/api/messages' from origin 'https://'
has been blocked by CORS policy: Response to preflight request doesn't pass access control check:
No 'Access-Control-Allow-Origin' header is present on the requested resource.
```

This was already anticipated in the ThruBox-Client consumer docs/comments (see Chainvoice's `relayClient.js` and `vite.config.js`), which document proxying as the only supported workaround today:

"The relay serves no CORS headers, so a direct cross-origin request from the browser fails its preflight... Production is expected to reach the relay through a reverse proxy that supplies CORS."

That workaround is fine for consumers willing to run their own reverse proxy, but ThruBox-Server is published as a general-purpose relay (npm SDK + GHCR image) — any consumer that wants to call it directly from the browser without standing up a proxy currently can't.

Proposed fix

Add CORS middleware to the handler chain in `cmd/relay/main.go`, alongside the existing `APIKeyAuth`/`RateLimiter` middleware:

  • Handle preflight `OPTIONS` requests explicitly (the current `http.ServeMux` routes have no `OPTIONS` handler, so preflights currently 404 in addition to missing headers).
  • Set `Access-Control-Allow-Origin`, `Access-Control-Allow-Methods` (GET, POST, DELETE), and `Access-Control-Allow-Headers` (at minimum `Content-Type`, and `X-API-Key` when `security.api_key` is configured).
  • Make allowed origins configurable (new `security.allowed_origins` config key + `RELAY_SECURITY_ALLOWED_ORIGINS` env override, following the existing pattern in `internal/config/config.go`) rather than hardcoding `*`, so self-hosted operators can restrict it if they want to.
  • Document the new config in README's Configuration table, and note that consumers can now either proxy (existing approach) or call the relay directly if their origin is allowlisted.

Notes

  • Not urgent for Chainvoice's current deployment specifically — that's being fixed independently via a Vercel rewrite (same-origin proxy), matching the already-documented intended setup.
  • This is about unblocking other ThruBox consumers who don't have a proxy in front of the relay.

Metadata

Metadata

Assignees

No one assigned

    Labels

    documentationChanges to documentation filesenhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions