Files
webman-buildadmin/app/common/library/admin/WebSocketConfigHelper.php

69 lines
2.1 KiB
PHP

<?php
declare(strict_types=1);
namespace app\common\library\admin;
use Webman\Http\Request;
final class WebSocketConfigHelper
{
public static function wsUrl(?Request $request = null): string
{
$url = trim((string) env('H5_WEBSOCKET_URL', ''));
if ($url !== '' && $request !== null && self::isLoopbackWsUrl($url) && !self::isLoopbackRequestHost($request)) {
$url = '';
}
if ($url !== '') {
return $url;
}
if ($request !== null) {
$proto = strtolower((string) $request->header('x-forwarded-proto', ''));
if ($proto === '') {
$proto = strtolower((string) $request->header('x-forwarded-protocol', ''));
}
$isHttps = $proto === 'https'
|| strtolower((string) $request->header('x-forwarded-ssl', '')) === 'on'
|| strtolower((string) $request->header('x-scheme', '')) === 'https';
$scheme = $isHttps ? 'wss' : 'ws';
$host = trim((string) $request->header('host', ''));
if ($host === '') {
$host = trim((string) $request->header('x-forwarded-host', ''));
}
if ($host !== '') {
return $scheme . '://' . $host . '/ws/';
}
}
return 'ws://127.0.0.1:3131/ws/';
}
private static function isLoopbackWsUrl(string $url): bool
{
$host = parse_url($url, PHP_URL_HOST);
if (!is_string($host) || $host === '') {
return false;
}
$host = strtolower($host);
return in_array($host, ['127.0.0.1', 'localhost', '::1'], true);
}
private static function isLoopbackRequestHost(Request $request): bool
{
$host = strtolower(trim((string) $request->host(true)));
if ($host === '') {
$host = strtolower(trim((string) $request->header('host', '')));
}
if ($host === '') {
return false;
}
$hostOnly = preg_split('/:/', $host)[0] ?? $host;
return in_array($hostOnly, ['127.0.0.1', 'localhost', '::1'], true);
}
}