harden database interactions and improve error handling
This commit is contained in:
@@ -0,0 +1,28 @@
|
||||
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));
|
||||
});
|
||||
Reference in New Issue
Block a user