import { NextRequest, NextResponse } from "next/server"; import { auth, getAuthSession } from "@/lib/auth"; import { sanitizeFilePath } from "@/lib/security/sanitize"; import * as fs from "node:fs"; import * as path from "node:path"; export async function GET(req: NextRequest) { const session = await getAuthSession(req.headers); if (!session) return NextResponse.json({ error: "Unauthorized" }, { status: 401 }); const mcBase = path.resolve(process.env.MC_SERVER_PATH ?? "/opt/minecraft/server"); const filePath = req.nextUrl.searchParams.get("path") ?? ""; let resolvedPath: string; try { resolvedPath = sanitizeFilePath(filePath, mcBase); } catch { return NextResponse.json({ error: "Invalid path" }, { status: 400 }); } if (!fs.existsSync(resolvedPath) || fs.statSync(resolvedPath).isDirectory()) { return NextResponse.json({ error: "File not found" }, { status: 404 }); } const fileName = path.basename(resolvedPath); const fileBuffer = fs.readFileSync(resolvedPath); return new NextResponse(fileBuffer, { headers: { "Content-Disposition": `attachment; filename="${encodeURIComponent(fileName)}"`, "Content-Type": "application/octet-stream", "Content-Length": String(fileBuffer.length), // Prevent XSS via content sniffing "X-Content-Type-Options": "nosniff", }, }); }