2026-05-24 15:41:00 +02:00
|
|
|
<?php
|
|
|
|
|
/**
|
|
|
|
|
* Proxy class for forwarding Deal API requests.
|
|
|
|
|
*/
|
|
|
|
|
class DealProxy
|
|
|
|
|
{
|
|
|
|
|
private $logFile;
|
|
|
|
|
|
|
|
|
|
public function __construct()
|
|
|
|
|
{
|
|
|
|
|
$this->logFile = __DIR__ . '/proxy.log';
|
|
|
|
|
}
|
|
|
|
|
|
2026-05-24 18:13:22 +02:00
|
|
|
private function logMessage($message)
|
2026-05-24 15:41:00 +02:00
|
|
|
{
|
|
|
|
|
$date = date('Y-m-d H:i:s');
|
|
|
|
|
file_put_contents($this->logFile, "[$date] $message\n", FILE_APPEND);
|
|
|
|
|
}
|
|
|
|
|
|
2026-06-28 12:15:15 +02:00
|
|
|
// private function buildTargetUrl()
|
|
|
|
|
// {
|
|
|
|
|
// $path = isset($_GET['path']) ? $_GET['path'] : '';
|
|
|
|
|
// unset($_GET['path']);
|
|
|
|
|
// $query = http_build_query($_GET);
|
|
|
|
|
//
|
|
|
|
|
// //$apiUrl = "https://api.joywork.ru/" . ltrim($path, '/');
|
|
|
|
|
//
|
|
|
|
|
// $baseUrl = 'https://10.91.76.101';
|
|
|
|
|
//
|
|
|
|
|
// $apiUrl = rtrim($baseUrl, '/') . '/' . ltrim($path, '/');
|
|
|
|
|
//
|
|
|
|
|
// if ($query) {
|
|
|
|
|
// $apiUrl .= '?' . $query;
|
|
|
|
|
// }
|
|
|
|
|
// return $apiUrl;
|
|
|
|
|
// }
|
|
|
|
|
|
2026-05-24 18:13:22 +02:00
|
|
|
private function buildTargetUrl()
|
2026-05-24 15:41:00 +02:00
|
|
|
{
|
2026-05-24 18:13:22 +02:00
|
|
|
$path = isset($_GET['path']) ? $_GET['path'] : '';
|
2026-05-24 15:41:00 +02:00
|
|
|
unset($_GET['path']);
|
2026-06-28 12:15:15 +02:00
|
|
|
|
|
|
|
|
$pathParts = explode('?', $path, 2);
|
|
|
|
|
$cleanPath = ltrim($pathParts[0], '/');
|
|
|
|
|
|
|
|
|
|
$queryParams = $_GET;
|
|
|
|
|
if (isset($pathParts[1]) && $pathParts[1]) {
|
|
|
|
|
parse_str($pathParts[1], $pathQuery);
|
|
|
|
|
$queryParams = array_merge($queryParams, $pathQuery);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$query = http_build_query($queryParams);
|
|
|
|
|
|
|
|
|
|
$baseUrl = 'https://10.91.76.101';
|
|
|
|
|
$apiUrl = rtrim($baseUrl, '/') . '/' . $cleanPath;
|
|
|
|
|
|
2026-05-24 15:41:00 +02:00
|
|
|
if ($query) {
|
|
|
|
|
$apiUrl .= '?' . $query;
|
|
|
|
|
}
|
2026-06-28 12:15:15 +02:00
|
|
|
|
2026-05-24 15:41:00 +02:00
|
|
|
return $apiUrl;
|
|
|
|
|
}
|
|
|
|
|
|
2026-05-24 18:13:22 +02:00
|
|
|
private function buildHeaders()
|
2026-05-24 15:41:00 +02:00
|
|
|
{
|
2026-05-24 18:13:22 +02:00
|
|
|
$headers = array(
|
2026-05-24 15:41:00 +02:00
|
|
|
'Accept: application/json',
|
2026-06-28 12:15:15 +02:00
|
|
|
'Host: api.joywork.ru',
|
2026-05-24 18:13:22 +02:00
|
|
|
);
|
2026-05-24 15:41:00 +02:00
|
|
|
|
|
|
|
|
// Preserve original Content-Type if present
|
2026-05-24 18:13:22 +02:00
|
|
|
$originalContentType = isset($_SERVER['CONTENT_TYPE']) ? $_SERVER['CONTENT_TYPE'] : '';
|
2026-05-24 15:41:00 +02:00
|
|
|
if ($originalContentType) {
|
|
|
|
|
$headers[] = 'Content-Type: ' . $originalContentType;
|
|
|
|
|
$this->logMessage("Incoming Content-Type: '$originalContentType'");
|
|
|
|
|
} else {
|
|
|
|
|
$this->logMessage('WARNING: Incoming Content-Type not detected');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Pass session cookie if exists
|
|
|
|
|
if (!empty($_COOKIE['PHPSESSID'])) {
|
|
|
|
|
$headers[] = 'Cookie: PHPSESSID=' . $_COOKIE['PHPSESSID'];
|
|
|
|
|
}
|
|
|
|
|
// Pass custom header from Vue if present
|
|
|
|
|
if (!empty($_SERVER['HTTP_X_SESSION_ID'])) {
|
|
|
|
|
$headers[] = 'X-Session-ID: ' . $_SERVER['HTTP_X_SESSION_ID'];
|
|
|
|
|
}
|
|
|
|
|
return $headers;
|
|
|
|
|
}
|
|
|
|
|
|
2026-05-24 18:13:22 +02:00
|
|
|
private function forwardRequest($targetUrl, $headers, $method, $body)
|
2026-05-24 15:41:00 +02:00
|
|
|
{
|
|
|
|
|
$ch = curl_init();
|
2026-05-24 18:13:22 +02:00
|
|
|
curl_setopt_array($ch, array(
|
2026-05-24 15:41:00 +02:00
|
|
|
CURLOPT_URL => $targetUrl,
|
|
|
|
|
CURLOPT_RETURNTRANSFER => true,
|
|
|
|
|
CURLOPT_CUSTOMREQUEST => $method,
|
|
|
|
|
CURLOPT_POSTFIELDS => $body,
|
|
|
|
|
CURLOPT_HTTPHEADER => $headers,
|
2026-07-07 12:26:10 +02:00
|
|
|
CURLOPT_HEADER => true,
|
2026-05-24 18:13:22 +02:00
|
|
|
));
|
2026-05-24 15:41:00 +02:00
|
|
|
|
2026-06-28 12:15:15 +02:00
|
|
|
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
|
|
|
|
|
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
|
|
|
|
|
|
2026-05-24 15:41:00 +02:00
|
|
|
$response = curl_exec($ch);
|
|
|
|
|
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
2026-07-07 12:26:10 +02:00
|
|
|
$headerSize = curl_getinfo($ch, CURLINFO_HEADER_SIZE);
|
2026-05-24 15:41:00 +02:00
|
|
|
$curlError = curl_error($ch);
|
2026-07-07 12:26:10 +02:00
|
|
|
curl_close($ch);
|
|
|
|
|
|
2026-05-24 15:41:00 +02:00
|
|
|
if ($curlError) {
|
|
|
|
|
$this->logMessage('cURL Error: ' . $curlError);
|
2026-07-07 12:26:10 +02:00
|
|
|
http_response_code(500);
|
|
|
|
|
echo $curlError;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$responseHeaders = substr($response, 0, $headerSize);
|
|
|
|
|
$responseBody = substr($response, $headerSize);
|
|
|
|
|
|
|
|
|
|
preg_match_all('/^([^:]+):\s*(.+)$/m', $responseHeaders, $matches);
|
|
|
|
|
if (isset($matches[1])) {
|
|
|
|
|
for ($i = 0; $i < count($matches[1]); $i++) {
|
|
|
|
|
$hName = trim($matches[1][$i]);
|
|
|
|
|
$hValue = trim($matches[2][$i]);
|
|
|
|
|
if (strcasecmp($hName, 'Content-Type') === 0 ||
|
|
|
|
|
strcasecmp($hName, 'Content-Disposition') === 0 ||
|
|
|
|
|
strcasecmp($hName, 'Content-Length') === 0 ||
|
|
|
|
|
strcasecmp($hName, 'Content-Transfer-Encoding') === 0 ||
|
|
|
|
|
strcasecmp($hName, 'Cache-Control') === 0 ||
|
|
|
|
|
strcasecmp($hName, 'Pragma') === 0) {
|
|
|
|
|
header("$hName: $hValue");
|
|
|
|
|
}
|
|
|
|
|
}
|
2026-05-24 15:41:00 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
http_response_code($httpCode);
|
2026-07-07 12:26:10 +02:00
|
|
|
echo $responseBody;
|
2026-05-24 15:41:00 +02:00
|
|
|
}
|
|
|
|
|
|
2026-06-28 12:34:43 +02:00
|
|
|
private function buildMultipartBody()
|
|
|
|
|
{
|
|
|
|
|
$boundary = '----FormBoundary' . uniqid();
|
|
|
|
|
$body = '';
|
|
|
|
|
|
|
|
|
|
foreach ($_POST as $key => $value) {
|
|
|
|
|
$body .= "--{$boundary}\r\n";
|
|
|
|
|
$body .= "Content-Disposition: form-data; name=\"{$key}\"\r\n\r\n";
|
|
|
|
|
$body .= "{$value}\r\n";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
foreach ($_FILES as $key => $file) {
|
|
|
|
|
if ($file['error'] === UPLOAD_ERR_OK) {
|
|
|
|
|
$body .= "--{$boundary}\r\n";
|
|
|
|
|
$body .= "Content-Disposition: form-data; name=\"{$key}\"; filename=\"{$file['name']}\"\r\n";
|
|
|
|
|
$body .= "Content-Type: {$file['type']}\r\n\r\n";
|
|
|
|
|
$body .= file_get_contents($file['tmp_name']) . "\r\n";
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$body .= "--{$boundary}--\r\n";
|
|
|
|
|
|
|
|
|
|
return ['body' => $body, 'boundary' => $boundary];
|
|
|
|
|
}
|
|
|
|
|
|
2026-05-24 18:13:22 +02:00
|
|
|
public function handle()
|
2026-05-24 15:41:00 +02:00
|
|
|
{
|
2026-06-28 12:15:15 +02:00
|
|
|
$this->logMessage('=== PROXY REQUEST START ===');
|
|
|
|
|
$this->logMessage('Method: ' . $_SERVER['REQUEST_METHOD']);
|
|
|
|
|
$this->logMessage('GET params: ' . print_r($_GET, true));
|
|
|
|
|
$this->logMessage('HTTP_X_SESSION_ID: ' . (isset($_SERVER['HTTP_X_SESSION_ID']) ? $_SERVER['HTTP_X_SESSION_ID'] : 'NOT SET'));
|
|
|
|
|
$this->logMessage('HTTP_COOKIE: ' . (isset($_SERVER['HTTP_COOKIE']) ? $_SERVER['HTTP_COOKIE'] : 'NOT SET'));
|
|
|
|
|
$this->logMessage('Raw input: ' . file_get_contents('php://input'));
|
2026-06-28 12:34:43 +02:00
|
|
|
$this->logMessage('FILES: ' . print_r($_FILES, true));
|
|
|
|
|
$this->logMessage('POST: ' . print_r($_POST, true));
|
2026-06-28 12:15:15 +02:00
|
|
|
|
|
|
|
|
// CORS headers
|
2026-05-24 15:41:00 +02:00
|
|
|
header('Access-Control-Allow-Origin: *');
|
|
|
|
|
header('Access-Control-Allow-Credentials: true');
|
|
|
|
|
header('Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS');
|
|
|
|
|
header('Access-Control-Allow-Headers: Accept, Content-Type, X-Requested-With, Authorization');
|
|
|
|
|
if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') {
|
|
|
|
|
http_response_code(204);
|
|
|
|
|
exit;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$targetUrl = $this->buildTargetUrl();
|
|
|
|
|
$headers = $this->buildHeaders();
|
|
|
|
|
$method = $_SERVER['REQUEST_METHOD'];
|
2026-06-28 12:34:43 +02:00
|
|
|
|
|
|
|
|
$originalContentType = isset($_SERVER['CONTENT_TYPE']) ? $_SERVER['CONTENT_TYPE'] : '';
|
|
|
|
|
|
|
|
|
|
if (strpos($originalContentType, 'multipart/form-data') !== false && !empty($_FILES)) {
|
|
|
|
|
$multipart = $this->buildMultipartBody();
|
|
|
|
|
$body = $multipart['body'];
|
|
|
|
|
$headers = array_filter($headers, function($h) {
|
|
|
|
|
return strpos($h, 'Content-Type:') === false;
|
|
|
|
|
});
|
|
|
|
|
$headers[] = 'Content-Type: multipart/form-data; boundary=' . $multipart['boundary'];
|
|
|
|
|
$this->logMessage('Rebuilt multipart body from $_POST/$_FILES');
|
|
|
|
|
} else {
|
|
|
|
|
$body = file_get_contents('php://input');
|
|
|
|
|
}
|
|
|
|
|
|
2026-05-24 15:41:00 +02:00
|
|
|
$this->logMessage('Forwarding request to ' . $targetUrl);
|
|
|
|
|
$this->forwardRequest($targetUrl, $headers, $method, $body);
|
|
|
|
|
}
|
2026-05-24 18:35:05 +02:00
|
|
|
}
|