# Medya gateway: kapsam ve cPanel kurulumu

Bu teslimatın çalıştırılan tek dosyası `gateway.php` dosyasıdır. Composer veya üçüncü taraf PHP paketi gerektirmez; **64 bit PHP 8.2+ ve PHP cURL eklentisi** gerekir. Mevcut proje dosyaları değiştirilmemiştir.

## Mimari sınır: bu betik bağlantı paylaşmaz

Bu dosya kontrollü, doğrudan akış ve indirme proxy'sidir. Her istemci isteği ayrı PHP worker ve ayrı upstream isteği kullanır. Eşzamanlı N istemcinin aynı kaynağı istemesi N upstream isteğine yol açar. Redirect kullanılıyorsa ilave sıralı istekler oluşur. Bu sürüm ilk gereksinimdeki **tek kaynak bağlantısını çok istemciye çoğaltmayı sağlamaz**.

PHP HTTP istekleri birbirinden bağımsızdır. Tek bağlantıyı paylaşmak için sürekli çalışan bir üretici ve istemcileri besleyecek ortak ring buffer/IPC gerekir. Aynı PHP dosyasını CLI üreticisi ve HTTP tüketicisi olarak yazmak mümkün olsa da bu, sürekli süreç yönetimi ve ortak tampon gereksinimini kaldırmaz; standart paylaşımlı cPanel için güvenilir bir varsayım değildir. Dosya kilidi istekleri sıraya sokar, bağlantıyı çoğaltmaz.

Gerçek fan-out için yönetebildiğiniz bir sunucuda tek üretici, sınırlı ortak tampon ve ayrı dağıtım katmanı kurun. HLS zaten playlist, segment ve bazen anahtar dosyaları için ayrı HTTP istekleri kullanır; tek TCP bağlantısı ile tek medya aboneliği aynı kavram değildir. HLS segment cache ve eşzamanlı cache doldurma kilidi yinelenen indirmeleri azaltabilir, ancak kendiliğinden tek canlı upstream bağlantısı garantisi vermez. Kullanıcıya özel yetkilendirme ve Range kuralları cache anahtarında ayrıca ele alınmalıdır.

Sıfır tampon, sınırsız yavaş istemci, kayıpsızlık ve sınırsız eşzamanlılık birlikte garanti edilemez. Yavaş tüketici için geciktirme, bağlantı kesme veya ek tampon politikası gerekir. Örneğin 8 Mbit/s akışın 100 istemciye iletilmesi, protokol ek yükü hariç yaklaşık 800 Mbit/s çıkış gerektirir; tek upstream bile bu çıkışı azaltmaz.

## Kurulum

1. **Kaynak erişimini hazırlayın.** Yalnızca erişmeye ve dağıtmaya yetkili olduğunuz içerikleri kullanın. Sohbette paylaşılan kaynak parolasını değiştirin; örnek kaynağa test isteği gönderilmedi.

2. **Ayrı HTTPS alt alan adı oluşturun.** cPanel Domains bölümünden örneğin `media-gateway.sirket.example` için ayrı document root oluşturun ve geçerli TLS sertifikasını etkinleştirin. Kimlik doğrulama anahtarını düz HTTP ile göndermeyin. Mümkünse erişimi şirket VPN'i veya web sunucusu IP listesiyle de sınırlandırın.

3. **PHP sürümünü ve eklentiyi kontrol edin.** cPanel MultiPHP Manager'da desteklenen PHP 8.2 veya üstünü seçin. Hosting sağlayıcınızdan ilgili web PHP sürümünde `curl` eklentisinin etkin olduğunu doğrulayın. Terminaldeki PHP ile web PHP sürümü farklı olabilir. CLI'da `php -m` çıktısında `curl` görünmelidir. SSL doğrulamasını kapatmayın; sertifika sorunlarında CA paketini hosting sağlayıcısı düzeltmelidir.

4. **Erişim anahtarı üretin.** Güvenilir yerel terminalde veya cPanel Terminal'de aşağıdaki komutu çalıştırın. Çıktıyı `gateway.php` başındaki `ACCESS_TOKEN` değerine yazın. Varsayılan değer değiştirilmeden betik 503 döner. Alternatif olarak web PHP sürecine `MEDIA_GATEWAY_TOKEN` ortam değişkeni sağlayabilirsiniz; terminalde `export` etmek PHP-FPM'e otomatik aktarmaz.

   ```sh
   php -r 'echo bin2hex(random_bytes(32)), PHP_EOL;'
   ```

5. **İzinli kaynakları girin.** `ALLOWED_ORIGINS` listesini gerçek, yetkili kaynaklarınızla değiştirin. Her kayıt küçük harfli `scheme://hostname:port` biçiminde, açık port numarasıyla ve sonunda `/` olmadan yazılmalıdır. HTTPS için `:443`, HTTP için `:80` dahil edilir. Gerekiyorsa `:2086` gibi özel port kullanılabilir. Yönlendirme hedeflerinin origin'leri ayrıca eklenmelidir; wildcard desteklenmez. HTTPS'ten HTTP'ye yönlendirme reddedilir. Bu sürüm yalnızca genel IPv4 hedeflerini destekler; intranet, loopback, link-local ve IPv6-only kaynaklar reddedilir. DNS sonucu doğrulanıp cURL bağlantısına sabitlenir. DNS'deki ilk IPv4 adresi kullanılır; otomatik IP failover yoktur.

6. **Dosyayı yükleyin.** File Manager ile yalnızca `gateway.php` dosyasını ayrı alt alan adının document root'una yükleyin. `tests` klasörünü yüklemeyin. Tipik dosya izni `0644` olabilir; hosting kullanıcı modelinize uygun en dar okuma iznini kullanın. Dosyanın PHP olarak çalıştığını doğrulayın; PHP kaynak kodunun statik sunulmasına izin vermeyin.

7. **PHP ve sunucu tamponlarını ayarlayın.** cPanel → Software → MultiPHP INI Editor içinde ilgili alan adı için aşağıdaki ayarları uygulayın. Bu seçenekler panelde yoksa sağlayıcıdan destek isteyin. Betik ayrıca çalışma anında PHP çıktı tamponlarını kaldırmayı ve gzip'i kapatmayı dener.

   ```ini
   output_buffering = Off
   zlib.output_compression = Off
   display_errors = Off
   log_errors = On
   max_execution_time = 3700
   ```

   PHP `flush()` çağrısı Nginx, Apache, LiteSpeed, CDN veya tarayıcı tamponlarını zorla kapatamaz. Betik `X-Accel-Buffering: no` gönderir; ön sunucunun bunu dikkate alması gerekir. Proxy buffering, response compression, PHP-FPM `request_terminate_timeout`, web sunucusu idle timeout ve CloudLinux LVE/Entry Process limitlerini sağlayıcıyla doğrulayın. Körlemesine `.htaccess` içine `php_flag` eklemeyin; PHP-FPM kurulumlarında 500 hatası doğurabilir.

8. **Çıkış ve kapasite limitlerini doğrulayın.** Hosting sağlayıcınızın kaynak portuna çıkışa ve uzun süreli medya aktarımına izin verdiğini öğrenin. Her aktif indirme/akış bir PHP worker tutar. Betik toplam aktarımı varsayılan 3600 saniye ile sınırlar; oynatıcı yeniden bağlanmalıdır. 10 saniye bağlantı süresi sınırı ve 30 saniyelik düşük hız kontrolü vardır. DNS çözümleyicisinin kendi zaman aşımı ayrı olabilir. Daha kısa hosting limitlerini PHP kodu kaldıramaz. Worker sayısı ve bant genişliği ölçülmeden performans garantisi verilemez.

## Kullanım

Kaynak URL'nin **tamamını bir kere URL-encode edin**. Kaynağın `&` karakterlerini gateway parametreleriyle karıştırmayın. PHP query string'i zaten çözer; betik ikinci kez `urldecode()` uygulamaz.

Özel oynatıcı/test istemcisi için önerilen erişim anahtarı başlığı:

```text
X-Gateway-Token: URETTIGINIZ_ANAHTAR
```

Bu başlık gönderildiğinde istekler istenen biçimi kullanır:

```text
https://media-gateway.sirket.example/gateway.php?url=URL_ENCODE_EDILMIS_KAYNAK
https://media-gateway.sirket.example/gateway.php?url=URL_ENCODE_EDILMIS_KAYNAK&action=download
```

Normal tarayıcı adres çubuğu özel başlık gönderemediğinden, şirket içi manuel kullanım için `&token=URETTIGINIZ_ANAHTAR` eklenebilir. Anahtar URL'ye yazılırsa tarayıcı geçmişinde ve erişim loglarında kalabilir. Tercihen VPN ve log maskeleme kullanın; uzun ömürlü anahtarları URL ile paylaşmayın. `url=` içindeki kaynak parolası da HTTPS kullanılsa bile gateway erişim loglarında bulunabilir. Betik kendi hata loguna URL/anahtar yazmaz, ancak hosting/CDN erişim loglarını kontrol edemez.

Yetkili ve sonlu bir segment ile komut satırı kontrolü:

```sh
curl --get 'https://media-gateway.sirket.example/gateway.php' \
  --header 'X-Gateway-Token: URETTIGINIZ_ANAHTAR' \
  --data-urlencode 'url=https://media.example.com/test/segment.ts' \
  --data-urlencode 'action=download' \
  --dump-header response-headers.txt \
  --output segment.ts
```

Gerçek anahtarı komut satırına yazmanın shell geçmişi riski vardır; otomatik testlerde secret yönetimi kullanın. `response-headers.txt` içinde `Content-Disposition: attachment; filename="segment.ts"` beklenir. Tarayıcı, kendi indirme ayarına göre dosyayı kaydeder veya konum sorar; betik zorunlu bir “Farklı Kaydet” penceresi açtıramaz. Sonsuz canlı akış indirmesi EOF'ye, istemci iptaline veya süre sınırına kadar devam eder; çevrimdışı incelemede sonlu segment tercih edin.

`action=download`, içerik gövdesini değiştirmez; güvenli bir dosya adıyla attachment başlığı ekler. Oynatma modu dosyayı doğrudan aktarır, HTML video oynatıcısı oluşturmaz. Tarayıcıda oynatılabilirlik tarayıcının codec/HLS desteğine bağlıdır. Content-Type bulunmazsa `application/octet-stream` kullanılır.

## HTTP davranışı ve bilinçli sınırlar

- GET ve HEAD desteklenir; diğer metotlar 405 döner. `User-Agent`, `Accept`, `Accept-Language`, `Range`, `If-Range`, ETag/tarih koşulları ve `Cache-Control` aktarılır. İstemci User-Agent göndermiyorsa sahte bir kimlik üretilmez.
- `Host` hedef URL'den oluşturulur. `Connection` ile belirtilen başlıklar ve diğer hop-by-hop başlıklar kopyalanmaz. `X-Forwarded-For`, `Origin`, `Referer` ve `X-Gateway-Token` kaynağa gönderilmez; aksi halde gateway kimlik bilgileri veya güven sınırları sızabilir.
- `Authorization` ve `Cookie` varsayılan olarak aktarılmaz. Özel oynatıcınız bunları açıkça upstream için gönderiyorsa `FORWARD_UPSTREAM_CREDENTIALS = true` yapılabilir. Gateway için HTTP Basic kullanıyorsanız bu seçeneği açmayın. Origin değiştiren yönlendirmeden sonra bu başlıklar tüm sonraki adımlarda silinir. Kaynak URL'nin query parametreleri korunur; sağlayıcının yönlendirme URL'sine kendisinin koyduğu sırlar otomatik temizlenmez.
- `Accept-Encoding: identity` talep edilir. Kaynak yine gzip gönderirse sıkıştırılmış baytlar ve Content-Encoding birlikte korunur; cURL içerik açılımı kapalıdır. HTTP chunk framing'i içerik değildir ve cURL tarafından çözülür.
- Upstream 206/304/404/416 gibi durumları, içerik tipi, uzunluk, Content-Range, Accept-Ranges, ETag ve Last-Modified aktarılır. Cache güvenliği için gateway `private, no-store` kullanır. Upstream Set-Cookie ve keyfi yanıt başlıkları aktarılmaz.
- Gövde diske veya tek büyük belleğe alınmaz; küçük cURL aktarım blokları echo/flush ile gönderilir. İşletim sistemi, TLS, cURL ve web sunucusu yine sınırlı tamponlar kullanır. Tam anlamıyla “sıfır tampon” değildir.
- Akış başladıktan sonra upstream hatası oluşursa artık HTTP durumunu değiştirmek mümkün değildir. Betik medya içine hata metni eklemez, aktarımı keser ve yalnızca sayısal cURL hata kodunu loglar. Content-Length olmayan erken sonlanan akışlarda istemci kesilmeyi her zaman HTTP üzerinden saptayamaz; oynatıcı medya sürekliliğini denetlemelidir.
- Betik **M3U/M3U8 URI'lerini yeniden yazmaz**. İndirilen playlist özgün baytlarını korur. Mutlak bağlantılar doğrudan kaynağa gider; göreli bağlantılar gateway URL'sine göre çözümlenirse bozulur. Özel oynatıcınız, kaynak playlist'in etkin URL'sini taban alarak alt playlist, segment, EXT-X-KEY ve EXT-X-MAP dahil tüm URI'leri çözmeli ve her isteği gateway'e sarmalamalıdır. Kaynak redirect kullanıyorsa etkin playlist URL'sini oynatıcı yapılandırmasında bilin. Alternatif tam HLS proxy'si URI yeniden yazımı gerektirir; bu sürüm bunu sağlamaz.
- CORS varsayılan olarak açılmamıştır. Ayrı origin'deki bir JavaScript oynatıcı için sabit izinli origin, OPTIONS ve izinli başlık politikası ayrıca gerekir. `*` ile anahtarlı bir proxy'yi herkese açmayın. Aynı origin veya sunucu taraflı test istemcisi kullanın. Erişim anahtarını herkese açık front-end koduna gömmeyin.

## Doğrulama

Yerel geliştirme ortamında:

```sh
php -l gateway.php
python tests/gateway_integration.py
```

Testler gerçek yayıncıya bağlanmaz. Geçici bir kopyada yalnızca yerel fixture sunucusu için loopback erişimi açılır; üretim dosyası değişmez. Gerçek IP koruması ayrıca devrede bırakılmış bir kopyada doğrulanır. Testler erişim kontrolünü, izinli hedef/yönlendirme sınırlarını, bayt bütünlüğünü, download, Range, HEAD, 304/404, gzip ve kademeli aktarımı kontrol eder. Bu testler gerçek cPanel dağıtımı veya eşzamanlı yük testi değildir.

## Kaynaklar

- [PHP flush: dış katmanların tamponlarını PHP yönetemez](https://www.php.net/manual/en/function.flush.php)
- [PHP cURL seçenekleri ve callback davranışları](https://www.php.net/manual/en/curl.constants.php)
- [libcurl CURLOPT_RESOLVE: DNS adresini bağlantıya sabitleme](https://curl.se/libcurl/c/CURLOPT_RESOLVE.html)
- [cPanel: PHP-FPM ile php.ini yönetimi](https://docs.cpanel.net/knowledge-base/web-services/how-to-manage-your-php.ini-directives-with-php-fpm/)
- [RFC 8216: HLS playlist, segment ve URI yapısı](https://www.rfc-editor.org/rfc/rfc8216)
