공통화 작업 및 워커 해더

This commit is contained in:
2026-04-07 15:39:41 +09:00
parent cba387de9d
commit 6a72ccebd5
51 changed files with 1185 additions and 2497 deletions

View File

@@ -38,6 +38,41 @@ function loadEnvFile($filePath) {
// .env 파일 로드 (한 단계 상위 디렉토리)
loadEnvFile(__DIR__ . '/../.env');
/**
* X-Forwarded-For 헤더에서 실제 클라이언트 IP 추출
* @return string 클라이언트 IP
*/
function getRealClientIP() {
// 1. X-Forwarded-For 헤더 확인 (여러 프록시를 거친 경우)
if (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
// "123.123.123.123, 192.168.10.1" 같은 형식에서 첫 번째 IP 추출
$ips = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);
$clientIP = trim($ips[0]); // 첫 번째 = 원래 클라이언트
// IP 형식 검증
if (filter_var($clientIP, FILTER_VALIDATE_IP)) {
return $clientIP;
}
}
// 2. X-Real-IP 헤더 확인 (단일 프록시)
if (!empty($_SERVER['HTTP_X_REAL_IP'])) {
if (filter_var($_SERVER['HTTP_X_REAL_IP'], FILTER_VALIDATE_IP)) {
return $_SERVER['HTTP_X_REAL_IP'];
}
}
// 3. CF-Connecting-IP (Cloudflare)
if (!empty($_SERVER['HTTP_CF_CONNECTING_IP'])) {
if (filter_var($_SERVER['HTTP_CF_CONNECTING_IP'], FILTER_VALIDATE_IP)) {
return $_SERVER['HTTP_CF_CONNECTING_IP'];
}
}
// 4. 기본값: REMOTE_ADDR (nginx가 set_real_ip_from으로 이미 변경함)
return $_SERVER['REMOTE_ADDR'] ?? '';
}
/**
* 날짜별 로그 기록 함수
* @param string $message 로그 내용
@@ -93,6 +128,8 @@ $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');
$requestInfo = [
'timestamp' => date('Y-m-d H:i:s'),
'method' => $_SERVER['REQUEST_METHOD'] ?? 'UNKNOWN',
@@ -102,7 +139,8 @@ $requestInfo = [
'get_params' => $_GET,
'post_data' => $rawData,
'client_ip' => $_SERVER['REMOTE_ADDR'] ?? '',
'real_ip' => $_SERVER['HTTP_X_FORWARDED_FOR'] ?? $_SERVER['HTTP_X_REAL_IP'] ?? $_SERVER['REMOTE_ADDR'] ?? '',
'real_ip' => getRealClientIP(),
'x_forwarded_for' => $_SERVER['HTTP_X_FORWARDED_FOR'] ?? '',
'user_agent' => $_SERVER['HTTP_USER_AGENT'] ?? '',
'referer' => $_SERVER['HTTP_REFERER'] ?? '',
'content_type' => $_SERVER['CONTENT_TYPE'] ?? $_SERVER['HTTP_CONTENT_TYPE'] ?? '',
@@ -135,10 +173,32 @@ try {
throw new Exception("No data received");
}
$data = null;
$contentType = $_SERVER['CONTENT_TYPE'] ?? $_SERVER['HTTP_CONTENT_TYPE'] ?? '';
// 1차 시도: JSON으로 직접 파싱
$data = json_decode($rawData, true);
if (json_last_error() !== JSON_ERROR_NONE) {
throw new Exception("Invalid JSON format: " . json_last_error_msg());
// JSON 파싱 성공
if ($data !== null && json_last_error() === JSON_ERROR_NONE) {
// 성공
}
// JSON 파싱 실패 → form-urlencoded 시도
else if (strpos($contentType, 'application/x-www-form-urlencoded') !== false || empty($contentType)) {
parse_str($rawData, $postData);
// post_data 키가 있으면 그 값을 JSON으로 파싱
if (isset($postData['post_data'])) {
$data = json_decode($postData['post_data'], true);
if (json_last_error() !== JSON_ERROR_NONE) {
throw new Exception("Invalid JSON format in post_data: " . json_last_error_msg());
}
} else {
// post_data 키가 없으면 form 데이터 자체를 사용
$data = $postData;
}
} else {
throw new Exception("Invalid JSON format: " . json_last_error_msg() . " | Data: " . substr($rawData, 0, 200));
}
if (empty($data)) {
@@ -149,7 +209,7 @@ try {
$payload = [
'request_data' => $data,
'received_at' => date('Y-m-d H:i:s'),
'client_ip' => $_SERVER['REMOTE_ADDR'] ?? 'unknown'
'client_ip' => getRealClientIP()
];
// 5. Redis 연결 시도 및 폴백 처리