Revisione/server/api/audio/[...path].get.ts

28 lines
940 B
TypeScript

import { createReadStream } from "fs";
import { resolve, normalize } from "path";
import { access } from "fs/promises";
export default defineEventHandler(async (event) => {
const pathParam = getRouterParam(event, "path") as string | string[];
const pathStr = Array.isArray(pathParam) ? pathParam.join("/") : pathParam;
// prevent path traversal
const baseDir = resolve(process.cwd(), "private/audio");
const filePath = normalize(resolve(baseDir, pathStr));
if (!filePath.startsWith(baseDir)) {
throw createError({ statusCode: 403, message: "Forbidden" });
}
try {
await access(filePath);
} catch {
throw createError({ statusCode: 404, message: "Audio not found" });
}
const ext = filePath.endsWith(".mp3") ? "audio/mpeg" : "audio/mpeg";
setHeader(event, "Content-Type", ext);
setHeader(event, "Cache-Control", "public, max-age=86400");
return sendStream(event, createReadStream(filePath));
});