Repository navigation
api: uniform CORS + an SSE event stream for frontends - #63
Merged
Merged
Conversation
5 tasks done
vynulldev
added a commit
that referenced
this pull request
Oct 10, 2026
Document the whole HTTP API with an OpenAPI 3.0 spec, and serve it with a self-hosted Swagger UI. The API is how the CLI, the web UI, and any external frontend drive a running Vynull, but it was documented only by the handlers themselves. Add docs/api/openapi.yaml covering every /api/* endpoint (56 paths, 75 operations, 31 schemas), and serve it at /api/openapi.yaml with a browsable Swagger UI at /api/docs. The UI bundle is vendored under docs/api/swagger/ and embedded, so it works offline with no CDN; the serving routes are always on, not gated on the web UI, so a headless daemon self-documents. The spec is the whole surface in one document, so it also describes the uniform CORS headers and the /api/events SSE stream whose behaviour lands in #63. Documenting them here keeps the spec complete rather than split across files. Docs and tooling only: a static spec file, the embedded UI assets, and the routes that serve them. No existing endpoint changes behaviour. The spec was audited field by field against the Go types it documents (every schema's properties checked against the serialized struct's JSON tags) and is drift-free.
Wrap the API mux in a CORS middleware so every endpoint sends permissive CORS (Access-Control-Allow-Origin: *, methods, Content-Type) and answers preflight OPTIONS uniformly — instead of the former per-handler patchwork where some endpoints set it and some (e.g. /api/status) didn't, and most POST endpoints had no preflight at all. This lets a browser frontend on another origin call the whole API. Vynull is a trusted-LAN tool with no auth, so this only makes the already open posture consistent. Existing per-handler CORS lines remain correct (the middleware sets the same header via Set, so no duplication — verified) and are now redundant; they can be removed in a later cleanup. Spec's CORS note updated to match.
Add GET /api/events, a Server-Sent Events stream pushing live deck +
now-playing state, so a frontend gets real-time updates instead of polling
/api/players at ~1 Hz. Each message is an 'event: state' carrying
{players, nowplaying} (the same shapes those endpoints return), sent on
change — effectively ~4 Hz while a deck is active (beat_age_ms keeps
moving) and nothing while idle, with a heartbeat to hold the connection.
A client interpolates the playhead between events with beat_age_ms, so a
few per second render smoothly. CORS applies via the mux middleware.
Documented in the spec; the 'live updates' note now points at the stream.
Verified live: text/event-stream, initial snapshot primed on connect.
vynulldev
force-pushed
the
api-cors-sse
branch
from
October 10, 2026 21:21
a4d4be1 to
bb6a6e6
Compare
vynulldev
marked this pull request as ready for review
October 10, 2026 21:23
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What & why
Two small API changes that let an external frontend drive Vynull: uniform CORS, and a live event stream.
These are the two gaps the frontends direction has been waiting on, so they go in together.
corsMiddlewarewraps the whole mux, setting the permissive CORS headers on every response and answering preflightOPTIONSuniformly. Vynull is a trusted-LAN tool with no auth and an already-open posture; several handlers set the same header by hand, so this just makes it consistent everywhere (preflight included) instead of a per-handler patchwork, so a UI served from another origin or device can call the API./api/events). A Server-Sent-Events endpoint that pushes live deck state as it changes, so a frontend gets push updates instead of polling/api/players. Self-contained inapi/events.goplus one route.The endpoints are documented in the OpenAPI spec in #58 (the spec is one document, so it owns the whole surface); this PR is code only.
Hardware testing
Both are HTTP-side only: a response-header middleware and a new read-only event stream. Neither touches the Pro DJ Link protocol, the load path, or anything a deck reacts to.
Checklist
go build ./...,go vet ./..., andgo test ./...passgofmt -l .is cleanGPL-3.0-or-later)