false, 'error' => 'ต้องเปิด PHP extension curl · Enable php-curl'], 500); } $method = $_SERVER['REQUEST_METHOD'] ?? 'GET'; if ($method !== 'POST') { json_response(['ok' => false, 'error' => 'Method not allowed'], 405); } $raw = file_get_contents('php://input'); if ($raw === false) { $raw = ''; } $contentLen = isset($_SERVER['CONTENT_LENGTH']) ? (int) $_SERVER['CONTENT_LENGTH'] : 0; if ($raw === '' && $contentLen > 0) { json_response([ 'ok' => false, 'error' => 'รับ body ไม่ได้ (มักเกิดจาก nginx client_max_body_size หรือ PHP post_max_size เล็กเกินไป) — ต้องตั้งอย่างน้อย ~20M สำหรับ /Admin/api/*.php · Request body was discarded (raise nginx body limit + PHP post_max_size)', ], 413); } $port = preg_replace('/[^0-9]/', '', (string)(getenv('GAME_NODE_PORT') ?: '3001')) ?: '3001'; $host = getenv('GAME_NODE_INTERNAL_HOST') ?: '127.0.0.1'; $target = 'http://' . $host . ':' . $port . '/Game/api/quiz-carry-plaque-upload'; $ch = curl_init($target); if ($ch === false) { json_response(['ok' => false, 'error' => 'curl init failed'], 500); } curl_setopt_array($ch, [ CURLOPT_POST => true, CURLOPT_POSTFIELDS => $raw, CURLOPT_HTTPHEADER => [ 'Accept: application/json', 'Content-Type: application/json', ], CURLOPT_RETURNTRANSFER => true, CURLOPT_TIMEOUT => 120, ]); $out = curl_exec($ch); $code = (int)curl_getinfo($ch, CURLINFO_HTTP_CODE); $err = curl_error($ch); curl_close($ch); if ($out === false || $out === '') { json_response([ 'ok' => false, 'error' => 'ไม่ต่อถึงเซิร์ฟเวอร์เกม (Node) — ตรวจ systemd/pm2 และพอร์ต ' . $port . ' · ' . $err, ], 502); } http_response_code($code > 0 ? $code : 500); header('Content-Type: application/json; charset=utf-8'); header('X-Content-Type-Options: nosniff'); header('Cache-Control: no-store'); echo $out;