70 lines
2.3 KiB
TypeScript

import { NextRequest, NextResponse } from 'next/server'
import { getServerSession } from 'next-auth'
import { authOptions } from '@/lib/auth'
import { hasSystemAdminPermission } from '@/lib/department-permission'
const MAX_TEST_SIZE_BYTES = 5 * 1024 * 1024
const RATE_LIMIT_WINDOW_MS = 60 * 1000
const RATE_LIMIT_MAX_REQUESTS = 10
const requestCounts = new Map<string, { count: number; resetAt: number }>()
function consumeRateLimit(userId: string): number | null {
const now = Date.now()
const current = requestCounts.get(userId)
if (!current || current.resetAt <= now) {
requestCounts.set(userId, { count: 1, resetAt: now + RATE_LIMIT_WINDOW_MS })
return null
}
if (current.count >= RATE_LIMIT_MAX_REQUESTS) {
return Math.max(1, Math.ceil((current.resetAt - now) / 1000))
}
current.count += 1
return null
}
// 下载测速API
export async function POST(request: NextRequest) {
try {
const session = await getServerSession(authOptions)
if (!session?.user) {
return NextResponse.json({ error: '请先登录' }, { status: 401 })
}
const user = session.user as any
if (!hasSystemAdminPermission(user.role, Boolean(user.isSuperAdmin))) {
return NextResponse.json({ error: '仅系统管理员可执行下载测速' }, { status: 403 })
}
const retryAfter = consumeRateLimit(String(user.id || 'unknown'))
if (retryAfter) {
return NextResponse.json(
{ error: '请求过于频繁,请稍后再试' },
{ status: 429, headers: { 'Retry-After': String(retryAfter) } },
)
}
const body = await request.json()
const size = body?.size === undefined ? 1024 * 1024 : Number(body.size)
if (!Number.isInteger(size) || size < 1 || size > MAX_TEST_SIZE_BYTES) {
return NextResponse.json(
{ error: `size 必须是 1 到 ${MAX_TEST_SIZE_BYTES} 之间的整数` },
{ status: 400 },
)
}
// 生成测试数据
const buffer = Buffer.alloc(size, 0)
return new NextResponse(buffer, {
headers: {
'Content-Type': 'application/octet-stream',
'Content-Length': size.toString(),
'Cache-Control': 'no-store',
}
})
} catch (error) {
console.error('下载测速失败:', error)
return NextResponse.json({ error: '下载测速失败' }, { status: 500 })
}
}