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 the real client IP from various headers // Cloudflare headers take precedence const clientIp = request.headers.get("cf-connecting-ip") || // Cloudflare request.headers.get("x-forwarded-for")?.split(",")[0]?.trim() || // First IP in chain request.headers.get("x-real-ip") || // Nginx/Traefik request.ip || // Next.js fallback "unknown"; const userAgent = request.headers.get("user-agent") || ""; // Forward to Rybbit backend with proper headers const response = await fetch(`${RYBBIT_API_URL}/api/track`, { method: "POST", headers: { "Content-Type": "application/json", "X-Forwarded-For": clientIp, "X-Real-IP": clientIp, "User-Agent": userAgent, // Forward Cloudflare headers if present ...(request.headers.get("cf-ipcountry") && { "CF-IPCountry": request.headers.get("cf-ipcountry")!, }), ...(request.headers.get("cf-ray") && { "CF-Ray": request.headers.get("cf-ray")!, }), }, body: JSON.stringify(body), }); const data = await response.text(); 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", }, }); }