63 lines
1.9 KiB
PHP
63 lines
1.9 KiB
PHP
<?php
|
||
|
||
namespace App\Services;
|
||
|
||
use App\Models\Setting;
|
||
|
||
class BunnyCdnSigner
|
||
{
|
||
/**
|
||
* BunnyCDN Token Auth ile imzalı URL üret.
|
||
* Token Auth açık değilse orijinal URL'yi döndür.
|
||
*
|
||
* BunnyCDN token format:
|
||
* token = base64url( sha256( securityKey + urlPath + expires ) )
|
||
* final = https://cdn.example.com/path?token={token}&expires={timestamp}
|
||
*/
|
||
public static function sign(?string $url): ?string
|
||
{
|
||
if (!$url) return null;
|
||
|
||
$securityKey = Setting::get('bunnycdn_token_key', '');
|
||
if (!$securityKey) return $url; // token auth kapalı
|
||
|
||
// Only sign BunnyCDN URLs - other domains pass through unchanged.
|
||
$host = parse_url($url, PHP_URL_HOST) ?? "";
|
||
$bunny = str_ends_with($host, "b-cdn.net") || str_contains($host, "bunnycdn.com");
|
||
if (!$bunny) return $url;
|
||
|
||
$ttl = (int) Setting::get('bunnycdn_token_ttl', 120);
|
||
$expires = time() + ($ttl * 60);
|
||
|
||
// URL'den path kısmını al
|
||
$parsed = parse_url($url);
|
||
$path = $parsed['path'] ?? '/';
|
||
|
||
// BunnyCDN token hesapla
|
||
$hashableBase = $securityKey . $path . $expires;
|
||
$token = base64_encode(hash('sha256', $hashableBase, true));
|
||
$token = str_replace(['+', '/', '='], ['-', '_', ''], $token);
|
||
|
||
// Mevcut query string varsa koru
|
||
$separator = isset($parsed['query']) ? '&' : '?';
|
||
$base = $parsed['scheme'] . '://' . $parsed['host'] . $path;
|
||
if (isset($parsed['query'])) {
|
||
$base .= '?' . $parsed['query'];
|
||
}
|
||
|
||
return $base . $separator . 'token=' . $token . '&expires=' . $expires;
|
||
}
|
||
|
||
/**
|
||
* Birden fazla URL imzala (dub sources için)
|
||
*/
|
||
public static function signAll(array &$sources): void
|
||
{
|
||
foreach ($sources as &$s) {
|
||
if (isset($s['url'])) {
|
||
$s['url'] = self::sign($s['url']);
|
||
}
|
||
}
|
||
}
|
||
}
|