import { cookies } from 'next/headers'; import { NextRequest, NextResponse } from 'next/server'; import { hasValidOrigin } from '../../../../../lib/request-origin'; function getClientIp(request: NextRequest): string { const forwarded = request.headers.get('x-forwarded-for'); if (forwarded) { const firstIp = forwarded.split(',')[0].trim(); if (firstIp) return firstIp; } return request.headers.get('x-real-ip') ?? '127.0.0.1'; } async function getOpsToken(): Promise { const cookieStore = await cookies(); const isProduction = process.env.NODE_ENV === 'production' && process.env.NEXT_PUBLIC_APP_ENV === 'production'; return isProduction ? cookieStore.get('__Host-motorsignal_ops')?.value : cookieStore.get('__Host-motorsignal_ops')?.value ?? cookieStore.get('motorsignal_ops')?.value; } export async function GET(request: NextRequest) { const opsToken = await getOpsToken(); if (!opsToken) { return NextResponse.json( { detail: 'Authentication required.' }, { status: 401 } ); } const { searchParams } = new URL(request.url); const action = searchParams.get('action') || 'ping'; const clientIp = getClientIp(request); if (action === 'ping') { return NextResponse.json( { status: 'ok', client_ip: clientIp, server_target: 'MotorSignal Host Edge', timestamp: Date.now(), }, { headers: { 'Cache-Control': 'no-store, no-cache, must-revalidate', 'X-Client-IP': clientIp, }, } ); } if (action === 'download') { const rawBytes = parseInt(searchParams.get('bytes') || '2500000', 10); const byteCount = Math.min(Math.max(100000, isNaN(rawBytes) ? 2500000 : rawBytes), 10000000); const chunk = new Uint8Array(byteCount); // Fill pseudo-random patterns to prevent transparent gzip collapse for (let i = 0; i < byteCount; i += 4096) { chunk[i] = (i * 31) & 0xff; } return new Response(chunk, { status: 200, headers: { 'Content-Type': 'application/octet-stream', 'Content-Length': byteCount.toString(), 'Cache-Control': 'no-store, no-cache, no-transform', 'X-Client-IP': clientIp, }, }); } return NextResponse.json({ status: 'available', modes: ['client_to_server', 'server_to_external'], client_ip: clientIp, }); } export async function POST(request: NextRequest) { if (!hasValidOrigin(request)) { return NextResponse.json({ detail: 'Invalid request origin.' }, { status: 403 }); } const opsToken = await getOpsToken(); if (!opsToken) { return NextResponse.json( { detail: 'Authentication required.' }, { status: 401 } ); } const clientIp = getClientIp(request); const action = request.nextUrl.searchParams.get('action'); // 1. Client to server upload benchmark handler if (action === 'upload') { const t0 = Date.now(); const arrayBuffer = await request.arrayBuffer(); const durationMs = Math.max(1, Date.now() - t0); return NextResponse.json({ status: 'completed', received_bytes: arrayBuffer.byteLength, server_duration_ms: durationMs, client_ip: clientIp, tested_at: new Date().toISOString(), }); } // 2. Client to server speedtest audit recorder (forward to backend ops_audit) if (action === 'record_client_result') { const body = await request.json().catch(() => null); const baseUrl = process.env.MOTORSIGNAL_API_BASE_URL ?? 'https://api.motorsignal.app'; try { const response = await fetch(`${baseUrl}/api/v1/ops/infrastructure/speedtest`, { method: 'POST', headers: { authorization: `Bearer ${opsToken}`, 'content-type': 'application/json', accept: 'application/json', }, body: JSON.stringify({ mode: 'client_to_server', latency_ms: body?.latency_ms, download_mbps: body?.download_mbps, upload_mbps: body?.upload_mbps, client_ip: clientIp, }), cache: 'no-store', }); if (response.ok) { const data = await response.json(); return NextResponse.json(data); } } catch { // Non-fatal if backend audit log proxy fails } return NextResponse.json({ status: 'completed', mode: 'client_to_server', client_ip: clientIp, recorded: true, }); } // 3. Server to external upstream benchmark handler (default) const baseUrl = process.env.MOTORSIGNAL_API_BASE_URL ?? 'https://api.motorsignal.app'; try { const response = await fetch(`${baseUrl}/api/v1/ops/infrastructure/speedtest`, { method: 'POST', headers: { authorization: `Bearer ${opsToken}`, accept: 'application/json', }, cache: 'no-store', }); if (response.status === 401) { return NextResponse.json( { detail: 'Your Operations session has expired.' }, { status: 401 } ); } if (response.status === 403) { return NextResponse.json( { detail: 'You do not have authority to run network speedtests.' }, { status: 403 } ); } if (!response.ok) { return NextResponse.json( { detail: 'Operations speedtest service temporarily unavailable.' }, { status: response.status >= 500 ? response.status : 503 } ); } const data = await response.json(); return NextResponse.json(data); } catch { return NextResponse.json( { detail: 'Unable to connect to Operations platform.' }, { status: 503 } ); } }