공통화 작업 및 워커 해더
This commit is contained in:
@@ -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 연결 시도 및 폴백 처리
|
||||
|
||||
Reference in New Issue
Block a user