47 lines
1.9 KiB
TypeScript
47 lines
1.9 KiB
TypeScript
/**
|
|
* Resolves the dump whose media a route under `/api/dumps/:dumpId/` serves:
|
|
* its file (`routes/files.ts`), its thumbnail (`routes/thumbnails.ts`) or its
|
|
* waveform (`routes/waveforms.ts`). Media elements and `<img>`s can't send an
|
|
* Authorization header, so these routes take the viewer's media token from
|
|
* the query string, and are cached by the file's version.
|
|
*
|
|
* @module
|
|
*/
|
|
|
|
import type { Context } from "@oak/oak";
|
|
import { APIException } from "./api-exception.ts";
|
|
import { authenticateMedia } from "./auth.ts";
|
|
import { type Dump, dumpFileVersion } from "../../shared/dump.ts";
|
|
import { UUID_RE } from "../../shared/validation.ts";
|
|
import { getDump } from "../services/dump-service.ts";
|
|
|
|
/**
|
|
* Returns dump `dumpId` as the viewer of `ctx`'s `?token=` may see it, and the
|
|
* Cache-Control its media get: kept for good under a URL naming the file's
|
|
* current version (`?v=`, as `dumpFileVersion` gives), revalidated under any
|
|
* other, and never in a shared cache for a private dump. It also keeps the
|
|
* token out of the Referer of whatever the response links to.
|
|
*
|
|
* @throws {APIException} 400 when `dumpId` isn't an id, which names files on
|
|
* disk, and 404 when the viewer can't see the dump.
|
|
*/
|
|
export async function resolveMediaDump(
|
|
ctx: Context,
|
|
dumpId: string,
|
|
): Promise<{ dump: Dump; cacheControl: string }> {
|
|
if (!UUID_RE.test(dumpId)) throw new APIException(400, "Invalid dump ID");
|
|
const token = ctx.request.url.searchParams.get("token");
|
|
const viewerId = token ? await authenticateMedia(token) : null;
|
|
const dump = getDump(dumpId, viewerId ?? undefined);
|
|
ctx.response.headers.set("Referrer-Policy", "no-referrer");
|
|
const scope = dump.isPrivate ? "private" : "public";
|
|
const current = ctx.request.url.searchParams.get("v") ===
|
|
dumpFileVersion(dump);
|
|
return {
|
|
dump,
|
|
cacheControl: current
|
|
? `${scope}, max-age=31536000, immutable`
|
|
: `${scope}, no-cache`,
|
|
};
|
|
}
|