import { NextRequest, NextResponse } from 'next/server' import fs from 'fs/promises' import path from 'path' import env from '@/lib/env'; import resolveFilePath from '@/lib/file'; // 白名单:允许访问的文件扩展名 const allowedExtensions = ['.html', '.js', '.css', '.json', '.png', '.jpg', '.jpeg', '.gif', '.svg']; const basePath = path.join(process.cwd(), env('STATIC_FILE_PATH')) export async function GET(req: NextRequest, { params }: { params: Promise<{ path?: string[] }> } ) { const fileseg = (await params).path const filepath = resolveFilePath(fileseg, basePath, allowedExtensions, ['index.html']) if (filepath === null) { return NextResponse.json({ message: 'File not found' }, { status: 404 }) } try { // 获取文件扩展名以确定 MIME 类型 const extname = path.extname(filepath).toLowerCase(); if (!allowedExtensions.includes(extname)) { return NextResponse.json({ error: 'Forbidden file type' }, { status: 403 }); } // 设置响应头 let contentType = 'text/plain'; switch (extname) { case '.html': contentType = 'text/html'; break; case '.js': contentType = 'text/javascript'; break; case '.css': contentType = 'text/css'; break; case '.json': contentType = 'application/json'; break; case '.png': contentType = 'image/png'; break; case '.jpg': case '.jpeg': contentType = 'image/jpeg'; break; case '.gif': contentType = 'image/gif'; break; case '.svg': contentType = 'image/svg+xml'; break; default: contentType = 'text/plain'; } const responseHeaders = new Headers(); responseHeaders.set('Content-Type', contentType); // 返回文件内容 return new NextResponse(await fs.readFile(filepath), { status: 200, headers: responseHeaders }); } catch (err) { console.error(err); return NextResponse.json({ error: 'Internal Server Error' }, { status: 500 }); } }