| <?php |
| |
|
|
| |
| if ($_SERVER['REQUEST_URI'] === '/' || $_SERVER['REQUEST_URI'] === '') { |
| header('Content-Type: text/html; charset=utf-8'); |
| echo '<p>about:blank</p>'; |
| exit; |
| } |
|
|
| |
| if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') { |
| http_response_code(204); |
| header('Access-Control-Allow-Origin: *'); |
| header('Access-Control-Allow-Methods: GET, POST, PUT, DELETE, PATCH, OPTIONS'); |
| header('Access-Control-Allow-Headers: *'); |
| header('Access-Control-Max-Age: 86400'); |
| exit; |
| } |
|
|
| |
| $target = substr($_SERVER['REQUEST_URI'], 1); |
| $query = $_SERVER['QUERY_STRING']; |
| if ($query !== '') { |
| $target .= '?' . $query; |
| } |
| if (!preg_match('#^https?://#i', $target)) { |
| $target = 'http://' . $target; |
| } |
|
|
| $parts = parse_url($target); |
| if (!$parts || !isset($parts['host'])) { |
| http_response_code(400); |
| echo 'Invalid target URL provided.'; |
| exit; |
| } |
|
|
| |
| $requestHeaders = getallheaders(); |
| $forwardHeaders = []; |
|
|
| |
| $hopByHop = [ |
| 'connection', 'keep-alive', 'proxy-authenticate', |
| 'proxy-authorization', 'te', 'trailer', 'transfer-encoding', |
| 'upgrade' |
| ]; |
|
|
| foreach ($requestHeaders as $name => $value) { |
| $lower = strtolower($name); |
| |
| if (strpos($lower, 'cf-') === 0 || $lower === 'x-real-ip' || $lower === 'host') { |
| continue; |
| } |
| |
| if (in_array($lower, $hopByHop)) { |
| continue; |
| } |
| |
| if ($lower === 'accept-encoding') { |
| continue; |
| } |
| $forwardHeaders[] = "$name: $value"; |
| } |
|
|
| |
| $forwardHeaders[] = 'Host: ' . $parts['host']; |
|
|
| |
| $hasUserAgent = false; |
| foreach ($forwardHeaders as $h) { |
| if (stripos($h, 'User-Agent:') === 0) { |
| $hasUserAgent = true; |
| break; |
| } |
| } |
| if (!$hasUserAgent) { |
| $forwardHeaders[] = 'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36'; |
| } |
|
|
| |
| $ch = curl_init($target); |
| curl_setopt_array($ch, [ |
| CURLOPT_CUSTOMREQUEST => $_SERVER['REQUEST_METHOD'], |
| CURLOPT_HTTPHEADER => $forwardHeaders, |
| CURLOPT_RETURNTRANSFER => true, |
| CURLOPT_FOLLOWLOCATION => true, |
| CURLOPT_HEADER => true, // include headers in output |
| CURLOPT_TIMEOUT => 30, |
| CURLOPT_ENCODING => '', // accept any compression, decompress automatically |
| CURLOPT_SSL_VERIFYPEER => true, // keep enabled (HF has CA certs) |
| ]); |
|
|
| |
| $body = file_get_contents('php://input'); |
| if ($body !== '' && $body !== false) { |
| curl_setopt($ch, CURLOPT_POSTFIELDS, $body); |
| } |
|
|
| $response = curl_exec($ch); |
| $error = curl_error($ch); |
| $info = curl_getinfo($ch); |
| curl_close($ch); |
|
|
| if ($error) { |
| http_response_code(502); |
| echo 'Upstream server fetch failed. Please check the URL and network.'; |
| exit; |
| } |
|
|
| |
| $headerSize = $info['header_size']; |
| $responseHeaders = substr($response, 0, $headerSize); |
| $responseBody = substr($response, $headerSize); |
|
|
| |
| $headersArr = explode("\r\n", $responseHeaders); |
| $statusCode = 200; |
| $outHeaders = []; |
|
|
| foreach ($headersArr as $line) { |
| |
| if (stripos($line, 'HTTP/') === 0) { |
| preg_match('/\d{3}/', $line, $m); |
| $statusCode = (int)($m[0] ?? 200); |
| continue; |
| } |
| if (trim($line) === '') { |
| continue; |
| } |
|
|
| $colon = strpos($line, ':'); |
| if ($colon !== false) { |
| $name = substr($line, 0, $colon); |
| $value = trim(substr($line, $colon + 1)); |
| $lower = strtolower($name); |
|
|
| |
| if ($lower === 'content-security-policy' || $lower === 'x-frame-options') { |
| continue; |
| } |
| |
| if (in_array($lower, $hopByHop)) { |
| continue; |
| } |
| |
| if ($lower === 'content-encoding') { |
| continue; |
| } |
|
|
| $outHeaders[] = [$name, $value]; |
| } |
| } |
|
|
| |
| http_response_code($statusCode); |
|
|
| |
| header('Access-Control-Allow-Origin: *'); |
| header('Access-Control-Allow-Methods: *'); |
| header('Access-Control-Allow-Headers: *'); |
| header('Cache-Control: no-store, no-cache, must-revalidate, proxy-revalidate'); |
| header('Pragma: no-cache'); |
| header('Expires: 0'); |
|
|
| |
| foreach ($outHeaders as $h) { |
| header($h[0] . ': ' . $h[1]); |
| } |
|
|
| echo $responseBody; |