Switch to /api/v1 with token authentication #2

Closed
opened 2026-10-06 16:11:38 +02:00 by Sansan · 1 comment
Owner

Move all server calls from the deprecated legacy routes to /api/v1, with token authentication. The legacy routes still work but send a Deprecation: true header and will be removed later (see Sansan/MusicServer#31).

Do #1 (start sync with POST) first, or together with this.

Token flow

  • POST /api/v1/token with JSON {"password": "<API password>", "client_type": "web"} returns {"token", "expires_at", "client_type"}. The token is valid for 24 hours.
  • Send it on every /api/v1 request: Authorization: Bearer <token>.
  • A missing, unknown or expired token returns 401 with {"error": "..."}.
  • Token creation is rate-limited to 10 requests per minute per client (429). Request once and reuse.
  • If the server has no API_PASSWORD set, any password works. If it has DISABLE_SESSION_AUTH=true, no token is needed.

Suggested structure

  • One shared axios instance (for example src/api.js) with baseURL: window.__RUNTIME_CONFIG__.API_HOSTNAME + "/api/v1", instead of building URLs in each component.
  • A request interceptor that adds Authorization: Bearer <token>.
  • A response interceptor that, on 401, requests a new token once and retries the request once.
  • Keep the token in memory (or sessionStorage). Ask for the password once, or read it from runtime config if the server is open (API_PASSWORD empty).
  • <img src> for character images can't send headers: fetch the image with axios as a blob and use URL.createObjectURL, or keep using the legacy /character?name= until the server offers another way.

Endpoint mapping

Legacy (current) /api/v1
/music/rand, /music/rand/low, /music/addPlayed, /music/addQue, /music/info, /music/list, /music?song=, /music/all, /music/reset Same path under /api/v1/..., same responses
POST /sync, GET /sync/progress POST /api/v1/sync, GET /api/v1/sync/progress
/characters /api/v1/character/list
/character?name= /api/v1/character?name= (needs the token, see above)
POST /find (search page HTML) Unchanged, not part of /api/v1

Responses now also contain UUIDs: /music/info and /music/list have SoundtrackUuid and SongUuid. Statistics are available under /api/v1/statistics/... if statisticsModal.vue should show server data later.

The OpenAPI spec is at <server>/openapi (Swagger UI at /swagger/index.html).

Acceptance criteria

  • No calls to legacy routes remain (except /find)
  • Token requested once, reused and refreshed automatically on 401
  • Works with a password-protected server and with an open one
Move all server calls from the deprecated legacy routes to `/api/v1`, with token authentication. The legacy routes still work but send a `Deprecation: true` header and will be removed later (see Sansan/MusicServer#31). Do #1 (start sync with POST) first, or together with this. ## Token flow - `POST /api/v1/token` with JSON `{"password": "<API password>", "client_type": "web"}` returns `{"token", "expires_at", "client_type"}`. The token is valid for **24 hours**. - Send it on every `/api/v1` request: `Authorization: Bearer <token>`. - A missing, unknown or expired token returns **401** with `{"error": "..."}`. - Token creation is rate-limited to **10 requests per minute per client** (429). Request once and reuse. - If the server has no `API_PASSWORD` set, any password works. If it has `DISABLE_SESSION_AUTH=true`, no token is needed. ## Suggested structure - One shared axios instance (for example `src/api.js`) with `baseURL: window.__RUNTIME_CONFIG__.API_HOSTNAME + "/api/v1"`, instead of building URLs in each component. - A request interceptor that adds `Authorization: Bearer <token>`. - A response interceptor that, on 401, requests a new token once and retries the request once. - Keep the token in memory (or `sessionStorage`). Ask for the password once, or read it from runtime config if the server is open (`API_PASSWORD` empty). - `<img src>` for character images can't send headers: fetch the image with axios as a blob and use `URL.createObjectURL`, or keep using the legacy `/character?name=` until the server offers another way. ## Endpoint mapping | Legacy (current) | `/api/v1` | |---|---| | `/music/rand`, `/music/rand/low`, `/music/addPlayed`, `/music/addQue`, `/music/info`, `/music/list`, `/music?song=`, `/music/all`, `/music/reset` | Same path under `/api/v1/...`, same responses | | `POST /sync`, `GET /sync/progress` | `POST /api/v1/sync`, `GET /api/v1/sync/progress` | | `/characters` | `/api/v1/character/list` | | `/character?name=` | `/api/v1/character?name=` (needs the token, see above) | | `POST /find` (search page HTML) | Unchanged, not part of `/api/v1` | Responses now also contain UUIDs: `/music/info` and `/music/list` have `SoundtrackUuid` and `SongUuid`. Statistics are available under `/api/v1/statistics/...` if `statisticsModal.vue` should show server data later. The OpenAPI spec is at `<server>/openapi` (Swagger UI at `/swagger/index.html`). ## Acceptance criteria - No calls to legacy routes remain (except `/find`) - Token requested once, reused and refreshed automatically on 401 - Works with a password-protected server and with an open one
Author
Owner

Update from MusicServer (develop, commit 973ebf2): the API docs are now generated with Huma instead of swag.

  • Spec: OpenAPI 3.1 at /openapi.json (also /openapi.yaml, and OpenAPI 3.0 at /openapi-3.0.json). Interactive docs at /docs. /openapi redirects to /openapi.json. Only /api/v1 is documented; legacy routes are hidden but still work.
  • Health: GET /api/v1/health now exists and needs no token (returns {"status": "up"}).
  • Sync aliases removed: /sync/new, /sync/quick and /sync/new/full are gone. Use POST /sync and POST /sync/full.
  • Errors: every error body is {"error": "..."}. Invalid or missing parameters (for example ?song=abc, a malformed UUID, limit=0) now return 422 instead of 400.
  • Lists: empty lists are [], never null. Arrays in the spec are not nullable.
**Update from MusicServer (`develop`, commit 973ebf2):** the API docs are now generated with Huma instead of swag. - **Spec:** OpenAPI 3.1 at `/openapi.json` (also `/openapi.yaml`, and OpenAPI 3.0 at `/openapi-3.0.json`). Interactive docs at `/docs`. `/openapi` redirects to `/openapi.json`. Only `/api/v1` is documented; legacy routes are hidden but still work. - **Health:** `GET /api/v1/health` now exists and needs no token (returns `{"status": "up"}`). - **Sync aliases removed:** `/sync/new`, `/sync/quick` and `/sync/new/full` are gone. Use `POST /sync` and `POST /sync/full`. - **Errors:** every error body is `{"error": "..."}`. Invalid or missing parameters (for example `?song=abc`, a malformed UUID, `limit=0`) now return **422** instead of 400. - **Lists:** empty lists are `[]`, never `null`. Arrays in the spec are not nullable.
Sign in to join this conversation.
No labels
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: Sansan/MusicFrontend#2