/** * Serves the Bandcamp release the native player plays, resolved from its page * when playback starts. On any failure the player falls back to the embed. * * - `GET /api/bandcamp/tracks?url=&force=` — public. Answers the page's * tracks and their stream URLs; `force=1` skips the server's cache. * * @module */ import { Router } from "@oak/oak"; import type { APIResponse } from "../../shared/api.ts"; import { resolveBandcamp } from "../remote/bandcamp-streams.ts"; import type { Tralbum } from "../../shared/player.ts"; /** * Mounted by `api/main.ts` behind the error, Open Graph and CORS middleware. * An `APIException` thrown by a handler becomes the JSON error response there. */ const bandcampRouter: Router = new Router(); // Public: it reads a public page and answers the URLs that page gives any // visitor. bandcampRouter.get("/api/bandcamp/tracks", async (ctx) => { const url = ctx.request.url.searchParams.get("url") ?? ""; const force = ctx.request.url.searchParams.get("force") === "1"; const responseBody: APIResponse = { success: true, data: await resolveBandcamp(url, { force }), }; // Not in a shared cache: the signed URLs belong to one page fetch. An hour // is well inside their 24 hours. ctx.response.headers.set("Cache-Control", "private, max-age=3600"); ctx.response.body = responseBody; }); export default bandcampRouter;