import { NextRequest, NextResponse } from "next/server"; const RYBBIT_API_URL = process.env.NEXT_PUBLIC_RYBBIT_HOST || "https://rybbit.nodecrew.me"; export async function POST(request: NextRequest) { try { const body = await request.json(); // Get all possible IP sources for debugging const cfConnectingIp = request.headers.get("cf-connecting-ip"); const xForwardedFor = request.headers.get("x-forwarded-for"); const xRealIp = request.headers.get("x-real-ip"); // @ts-ignore - ip exists at runtime but not in types const nextJsIp = (request as any).ip; // Use the first available IP in priority order const clientIp = cfConnectingIp || // Cloudflare (most reliable) xForwardedFor?.split(",")[0]?.trim() || // First IP in chain xRealIp || // Nginx/Traefik nextJsIp || // Next.js fallback "unknown"; const userAgent = request.headers.get("user-agent") || ""; console.log("[Rybbit Proxy] IP Debug:", { cfConnectingIp, xForwardedFor, xRealIp, nextJsIp, finalIp: clientIp, userAgent: userAgent?.substring(0, 50), }); // Build headers to forward const forwardHeaders: Record = { "Content-Type": "application/json", "X-Forwarded-For": clientIp, "X-Real-IP": clientIp, "User-Agent": userAgent, }; // Forward original CF headers if present const cfCountry = request.headers.get("cf-ipcountry"); const cfRay = request.headers.get("cf-ray"); if (cfCountry) forwardHeaders["CF-IPCountry"] = cfCountry; if (cfRay) forwardHeaders["CF-Ray"] = cfRay; console.log("[Rybbit Proxy] Forwarding to Rybbit with headers:", Object.keys(forwardHeaders)); const response = await fetch(`${RYBBIT_API_URL}/api/track`, { method: "POST", headers: forwardHeaders, body: JSON.stringify(body), }); const data = await response.text(); console.log("[Rybbit Proxy] Response:", response.status, data.substring(0, 100)); return new NextResponse(data, { status: response.status, headers: { "Content-Type": "application/json", "Access-Control-Allow-Origin": "*", }, }); } catch (error) { console.error("[Rybbit Proxy] Error:", error); return new NextResponse( JSON.stringify({ error: "Proxy error" }), { status: 500, headers: { "Content-Type": "application/json" } } ); } } // Handle CORS preflight export async function OPTIONS() { return new NextResponse(null, { status: 200, headers: { "Access-Control-Allow-Origin": "*", "Access-Control-Allow-Methods": "POST, OPTIONS", "Access-Control-Allow-Headers": "Content-Type", }, }); }