49 lines
1.6 KiB
PHP
49 lines
1.6 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace Plugin\AzuraCastOnDemandHls\Cors;
|
|
|
|
use InvalidArgumentException;
|
|
|
|
/** Validates and canonicalizes web origins used by the HLS CORS allowlist. */
|
|
final class Origin
|
|
{
|
|
public static function normalize(string $origin): string
|
|
{
|
|
$origin = trim($origin);
|
|
if ('' === $origin || 'null' === strtolower($origin)) {
|
|
throw new InvalidArgumentException('A CORS origin must be an absolute HTTP or HTTPS origin.');
|
|
}
|
|
|
|
$parts = parse_url($origin);
|
|
if (false === $parts
|
|
|| !isset($parts['scheme'], $parts['host'])
|
|
|| isset($parts['user'], $parts['pass'], $parts['query'], $parts['fragment'])
|
|
|| (isset($parts['path']) && '/' !== $parts['path'])
|
|
) {
|
|
throw new InvalidArgumentException(sprintf('Invalid CORS origin: %s', $origin));
|
|
}
|
|
|
|
$scheme = strtolower($parts['scheme']);
|
|
$host = strtolower($parts['host']);
|
|
if (!in_array($scheme, ['http', 'https'], true)
|
|
|| '' === $host
|
|
|| !preg_match('/^[a-z0-9.-]+$/D', $host)
|
|
) {
|
|
throw new InvalidArgumentException(sprintf('Invalid CORS origin: %s', $origin));
|
|
}
|
|
|
|
$port = $parts['port'] ?? null;
|
|
if (null !== $port && ($port < 1 || $port > 65535)) {
|
|
throw new InvalidArgumentException(sprintf('Invalid CORS origin: %s', $origin));
|
|
}
|
|
|
|
if (('https' === $scheme && 443 === $port) || ('http' === $scheme && 80 === $port)) {
|
|
$port = null;
|
|
}
|
|
|
|
return $scheme . '://' . $host . (null === $port ? '' : ':' . $port);
|
|
}
|
|
}
|