jellyfin sidecar: server registry, video façade and byte pass-through
officer-jellyfin owns the whole Jellyfin contract: the instance URL, the access token, the Jellyfin user it belongs to and the DeviceId its sessions are keyed by. The platform side is a 17-line proxy holding no credentials. Servers are a registry, not a single row — this machine runs four instances and the owner switches between them. The password is never stored: it is traded once for an access token through AuthenticateByName, and only that token is persisted, encrypted. Two doors. /_officer/* is a hand-written JSON façade for the things the browser should not have to know — the user id in the path, the Fields lists that decide whether a grid has posters, the PlaybackInfo negotiation. /_jf/* is a GET-only, allow-listed byte pass-through for images, video, HLS and subtitles; it keeps Jellyfin's own paths because a master playlist references its segments relatively, so any renaming would mean rewriting m3u8 bodies. TranscodingUrl arrives with api_key=<access token> in its query string and would otherwise be handed straight to a video element. It is stripped before anything is returned; the pass-through re-adds the credential as a header. Video only — Officer's own player owns audio, so music collections are filtered out of the library list. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,21 @@
|
||||
import { createSidecarProxy } from '../../sidecar/create-proxy';
|
||||
|
||||
// /api/jellyfin/* — auth, then forward to officer-jellyfin. No routes of its own and no Jellyfin knowledge:
|
||||
// this file must never grow app logic.
|
||||
//
|
||||
// The sidecar owns the Jellyfin contract and holds its credentials.
|
||||
//
|
||||
// `timeoutSeconds` is generous because this proxy carries VIDEO. A direct-play stream holds one connection
|
||||
// open for the length of the film, and the first request against a fresh transcode waits on ffmpeg starting
|
||||
// up. The default 60s idle drop would cut both.
|
||||
|
||||
const proxy = createSidecarProxy({
|
||||
name: 'jellyfin',
|
||||
prefix: '/api/jellyfin',
|
||||
timeoutSeconds: 3600,
|
||||
});
|
||||
|
||||
export const jellyfinRouter = proxy.router;
|
||||
|
||||
/** Base URL of the sidecar's HTTP server, or null if it hasn't reported in yet. */
|
||||
export const getJellyfinServerUrl = proxy.getHttpUrl;
|
||||
Reference in New Issue
Block a user