diff --git a/worker/api_receiver.php b/worker/api_receiver.php index 796c18f..fd3e649 100644 --- a/worker/api_receiver.php +++ b/worker/api_receiver.php @@ -115,9 +115,21 @@ function writeLog($message, $level = 'ERROR') { } // 도우미 함수 정의 +function safeJsonEncode($value, $flags = 0, $depth = 512) { + try { + return json_encode($value, $flags | JSON_THROW_ON_ERROR, $depth); + } catch (JsonException $e) { + return false; + } +} + function apiResponse($error = null) { - $base = $error; - return json_encode($base); + $encoded = safeJsonEncode($error, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES); + if ($encoded === false) { + writeLog('JSON_ENCODE_FAIL | apiResponse encoding failed', 'ERROR'); + return '{"code":"E999","message":"Internal server error"}'; + } + return $encoded; } // 1. 응답 헤더 설정 (JSON) @@ -128,7 +140,12 @@ $protocol = isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on' ? "https" : " $fullUrl = $protocol . "://" . ($_SERVER['HTTP_HOST'] ?? 'localhost') . ($_SERVER['REQUEST_URI'] ?? ''); $rawData = file_get_contents('php://input'); -writeLog("REQUEST_INFO | " . json_encode($rawData, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), 'INFO'); +$rawDataLog = safeJsonEncode($rawData, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES); +if ($rawDataLog === false) { + writeLog('JSON_ENCODE_FAIL | failed to encode raw request data for logging', 'WARNING'); + $rawDataLog = '"json_encode_failed"'; +} +writeLog("REQUEST_INFO | " . $rawDataLog, 'INFO'); $requestInfo = [ 'timestamp' => date('Y-m-d H:i:s'), @@ -150,7 +167,12 @@ $requestInfo = [ 'server_protocol' => $_SERVER['SERVER_PROTOCOL'] ?? '', ]; -writeLog("REQUEST_INFO | " . json_encode($requestInfo, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), 'INFO'); +$requestInfoLog = safeJsonEncode($requestInfo, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES); +if ($requestInfoLog === false) { + writeLog('JSON_ENCODE_FAIL | failed to encode request metadata for logging', 'WARNING'); + $requestInfoLog = '"json_encode_failed"'; +} +writeLog("REQUEST_INFO | " . $requestInfoLog, 'INFO'); // ================================================================ // 2. 보안 키 체크 (URL 파라미터 key=값) @@ -231,7 +253,12 @@ try { $redis->select((int)$redisDatabase); // 'naver:raw_queue'라는 이름의 리스트에 저장 - $pushResult = $redis->lPush('naver:raw_queue', json_encode($payload)); + $encodedPayload = safeJsonEncode($payload, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES); + if ($encodedPayload === false) { + throw new Exception('Failed to encode payload for Redis queue'); + } + + $pushResult = $redis->lPush('naver:raw_queue', $encodedPayload); if (!$pushResult) { throw new Exception("Failed to push data to Redis queue"); @@ -255,7 +282,12 @@ try { // 파일로 저장 (타임스탬프 + 유니크ID) $filename = $fallbackDir . '/' . date('YmdHis') . '_' . uniqid() . '.json'; - $writeResult = file_put_contents($filename, json_encode($payload), LOCK_EX); + $encodedPayload = safeJsonEncode($payload, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES); + if ($encodedPayload === false) { + throw new Exception('Failed to encode payload for fallback file'); + } + + $writeResult = file_put_contents($filename, $encodedPayload, LOCK_EX); if ($writeResult === false) { throw new Exception("Failed to write fallback file");