Migrated admin and media APIs to Nitro

This commit is contained in:
lucast committed 2026-09-29 01:22:29 +02:00
1 parent ee5809a489
commit bca41b5e6f
18 files changed
+786 -1

No files matched your search

+98
View File
@@ -0,0 +1,98 @@
import { createReadStream } from "node:fs"
import { stat } from "node:fs/promises"
import path from "node:path"
import { assertMethod, getRouterParam, getRequestHeader, sendStream, setHeader, setResponseStatus } from "h3"
import { InvalidUploadPathError, resolveUploadFile, UploadFileNotFoundError } from "../../utils/upload-files"
const contentTypes: Record<string, string> = {
".aac": "audio/aac",
".flac": "audio/flac",
".jpeg": "image/jpeg",
".jpg": "image/jpeg",
".m4a": "audio/mp4",
".mp3": "audio/mpeg",
".mp4": "video/mp4",
".ogg": "audio/ogg",
".png": "image/png",
".wav": "audio/wav",
".webp": "image/webp",
}
function sendRangeNotSatisfiable(event: Parameters<typeof setResponseStatus>[0], size: number) {
setResponseStatus(event, 416)
setHeader(event, "Content-Range", `bytes */${size}`)
setHeader(event, "Accept-Ranges", "bytes")
setHeader(event, "Content-Length", 0)
return null
}
export default defineEventHandler(async (event) => {
assertMethod(event, ["GET", "HEAD"])
const relativePath = getRouterParam(event, "path")
if (!relativePath) {
setResponseStatus(event, 404)
return null
}
let file: { path: string }
try {
file = await resolveUploadFile(event, relativePath)
} catch (error) {
if (error instanceof InvalidUploadPathError || error instanceof UploadFileNotFoundError) {
setResponseStatus(event, 404)
return null
}
throw error
}
let metadata
try {
metadata = await stat(file.path)
} catch (error) {
if ((error as NodeJS.ErrnoException).code === "ENOENT") {
setResponseStatus(event, 404)
return null
}
throw error
}
if (!metadata.isFile()) {
setResponseStatus(event, 404)
return null
}
setHeader(event, "Accept-Ranges", "bytes")
setHeader(event, "Content-Type", contentTypes[path.extname(file.path).toLowerCase()] ?? "application/octet-stream")
const rangeHeader = getRequestHeader(event, "range")
let start = 0
let end = metadata.size - 1
if (rangeHeader) {
const match = /^bytes=(\d*)-(\d*)$/.exec(rangeHeader.trim())
if (!match || (!match[1] && !match[2]) || metadata.size === 0) {
return sendRangeNotSatisfiable(event, metadata.size)
}
if (!match[1]) {
const suffixLength = Number(match[2])
if (!Number.isSafeInteger(suffixLength) || suffixLength <= 0) return sendRangeNotSatisfiable(event, metadata.size)
start = Math.max(metadata.size - suffixLength, 0)
} else {
start = Number(match[1])
if (!Number.isSafeInteger(start)) return sendRangeNotSatisfiable(event, metadata.size)
if (match[2]) {
end = Number(match[2])
if (!Number.isSafeInteger(end)) return sendRangeNotSatisfiable(event, metadata.size)
}
}
if (start >= metadata.size || end < start) return sendRangeNotSatisfiable(event, metadata.size)
end = Math.min(end, metadata.size - 1)
setResponseStatus(event, 206)
setHeader(event, "Content-Range", `bytes ${start}-${end}/${metadata.size}`)
setHeader(event, "Content-Length", end - start + 1)
} else {
setHeader(event, "Content-Length", metadata.size)
}
if (event.node.req.method === "HEAD") return null
return sendStream(event, createReadStream(file.path, { start, end }))
})