true, CURLOPT_HEADER => true, CURLOPT_FOLLOWLOCATION => true, CURLOPT_MAXREDIRS => 5, CURLOPT_HTTPHEADER => $headers, CURLOPT_SSL_VERIFYPEER => false, CURLOPT_TIMEOUT => 30, CURLOPT_CONNECTTIMEOUT => 10, CURLOPT_ENCODING => '', // gzip/br otomatik çöz ]); $raw = curl_exec($ch); $info = [ 'code' => curl_getinfo($ch, CURLINFO_HTTP_CODE), 'hsize' => curl_getinfo($ch, CURLINFO_HEADER_SIZE), 'ctype' => curl_getinfo($ch, CURLINFO_CONTENT_TYPE) ?? '', 'final' => curl_getinfo($ch, CURLINFO_EFFECTIVE_URL), 'err' => curl_error($ch), ]; curl_close($ch); return [$raw, $info]; }; $UA = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36'; $baseHeaders = [ 'User-Agent: ' . $UA, 'Accept: */*', 'Accept-Language: tr-TR,tr;q=0.9,en;q=0.8', 'Accept-Encoding: identity', 'Referer: ' . $referer, 'Origin: ' . $origin, 'Sec-Fetch-Dest: empty', 'Sec-Fetch-Mode: cors', 'Sec-Fetch-Site: cross-site', ]; if (!empty($_SERVER['HTTP_RANGE'])) { $baseHeaders[] = 'Range: ' . $_SERVER['HTTP_RANGE']; } [$raw, $info] = $doFetch($url, $baseHeaders); // 403/401 → hotlink koruması olabilir; Origin'siz ve sadece Referer ile bir kez daha dene if (in_array($info['code'], [401, 403], true)) { $retryHeaders = array_values(array_filter($baseHeaders, function ($h) { return !preg_match('/^(Origin|Sec-Fetch-):/i', $h); })); [$raw2, $info2] = $doFetch($url, $retryHeaders); if (!in_array($info2['code'], [401, 403], true) && $raw2 !== false) { $raw = $raw2; $info = $info2; } } $httpCode = $info['code']; $hdrSize = $info['hsize']; $ctype = $info['ctype']; $finalUrl = $info['final']; $curlErr = $info['err']; if ($raw === false || $curlErr) { http_response_code(502); die('Upstream hatası: ' . $curlErr); } $body = substr($raw, $hdrSize); header('Access-Control-Allow-Origin: *'); header('Access-Control-Allow-Methods: GET, OPTIONS'); header('Access-Control-Allow-Headers: Range'); header('Access-Control-Expose-Headers: Content-Length, Content-Range, Content-Type'); http_response_code($httpCode); $isM3u8 = str_contains($ctype, 'mpegurl') || preg_match('/\.m3u8(\?|$)/i', strtok($url, '#')); if ($isM3u8 && str_starts_with(ltrim($body), '#EXTM3U')) { header('Content-Type: application/vnd.apple.mpegurl'); header('Cache-Control: no-cache'); $scheme = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') ? 'https' : 'http'; $proxyBase = $scheme . '://' . $_SERVER['HTTP_HOST'] . '/hls-proxy.php?ref=' . urlencode($referer) . '&url='; $baseDir = dirname($finalUrl) . '/'; $output = []; foreach (explode("\n", $body) as $line) { $line = rtrim($line, "\r"); if ($line === '') { $output[] = ''; continue; } if (str_starts_with($line, '#')) { $line = preg_replace_callback('/URI="([^"]+)"/', function ($m) use ($baseDir, $proxyBase) { $uri = $m[1]; if (!str_starts_with($uri, 'http')) $uri = $baseDir . $uri; return 'URI="' . $proxyBase . urlencode($uri) . '"'; }, $line); $output[] = $line; } else { if (!str_starts_with($line, 'http')) $line = $baseDir . $line; $output[] = $proxyBase . urlencode($line); } } echo implode("\n", $output); } else { if ($ctype) header('Content-Type: ' . $ctype); $len = strlen($body); if ($len) header('Content-Length: ' . $len); echo $body; }