From 09beb47b5008029284457dcd35d609cd4890c43d Mon Sep 17 00:00:00 2001 From: Jan Tuzil Date: Mon, 13 Nov 2023 13:56:02 -0500 Subject: [PATCH] RequestFactory: unify and fix host parsing --- src/Http/RequestFactory.php | 47 +++++++++++-------- .../Http/RequestFactory.proxy.forwarded.phpt | 4 +- 2 files changed, 29 insertions(+), 22 deletions(-) diff --git a/src/Http/RequestFactory.php b/src/Http/RequestFactory.php index 82522f8a..ac0e9bc3 100644 --- a/src/Http/RequestFactory.php +++ b/src/Http/RequestFactory.php @@ -89,11 +89,11 @@ private function getServer(Url $url): void if ( (isset($_SERVER[$tmp = 'HTTP_HOST']) || isset($_SERVER[$tmp = 'SERVER_NAME'])) - && preg_match('#^([a-z0-9_.-]+|\[[a-f0-9:]+\])(:\d+)?$#Di', $_SERVER[$tmp], $pair) + && $pair = $this->parseHost($_SERVER[$tmp]) ) { - $url->setHost(rtrim(strtolower($pair[1]), '.')); - if (isset($pair[2])) { - $url->setPort((int) substr($pair[2], 1)); + $url->setHost($pair[0]); + if (isset($pair[1])) { + $url->setPort($pair[1]); } elseif (isset($_SERVER['SERVER_PORT'])) { $url->setPort((int) $_SERVER['SERVER_PORT']); } @@ -321,22 +321,13 @@ private function useForwardedProxy(Url $url): ?string $url->setPort($url->getScheme() === 'https' ? 443 : 80); } - if (isset($proxyParams['host']) && count($proxyParams['host']) === 1) { - $host = $proxyParams['host'][0]; - $startingDelimiterPosition = strpos($host, '['); - if ($startingDelimiterPosition === false) { //IPv4 - $pair = explode(':', $host); - $url->setHost($pair[0]); - if (isset($pair[1])) { - $url->setPort((int) $pair[1]); - } - } else { //IPv6 - $endingDelimiterPosition = strpos($host, ']'); - $url->setHost(substr($host, strpos($host, '[') + 1, $endingDelimiterPosition - 1)); - $pair = explode(':', substr($host, $endingDelimiterPosition)); - if (isset($pair[1])) { - $url->setPort((int) $pair[1]); - } + if ( + isset($proxyParams['host']) && count($proxyParams['host']) === 1 + && $pair = $this->parseHost($proxyParams['host'][0]) + ) { + $url->setHost($pair[0]); + if (isset($pair[1])) { + $url->setPort($pair[1]); } } return $remoteAddr ?? null; @@ -378,6 +369,22 @@ private function useNonstandardProxy(Url $url): ?string } + /** + * @return array{}|array{0: string}|array{0: string, 1: int} + */ + private function parseHost(string $host): array + { + $pair = []; + if (preg_match('#^([a-z0-9_.-]+|\[[a-f0-9:]+\])(:\d+)?$#Di', $host, $matches)) { + $pair[] = rtrim(strtolower($matches[1]), '.'); + if (isset($matches[2])) { + $pair[] = (int) substr($matches[2], 1); + } + } + return $pair; + } + + /** @deprecated */ public function createHttpRequest(): Request { diff --git a/tests/Http/RequestFactory.proxy.forwarded.phpt b/tests/Http/RequestFactory.proxy.forwarded.phpt index c1a92659..3805db12 100644 --- a/tests/Http/RequestFactory.proxy.forwarded.phpt +++ b/tests/Http/RequestFactory.proxy.forwarded.phpt @@ -65,7 +65,7 @@ test('', function () { Assert::same('2001:db8:cafe::17', $factory->fromGlobals()->getRemoteHost()); $url = $factory->fromGlobals()->getUrl(); - Assert::same('2001:db8:cafe::18', $url->getHost()); + Assert::same('[2001:db8:cafe::18]', $url->getHost()); }); test('', function () { @@ -83,7 +83,7 @@ test('', function () { $url = $factory->fromGlobals()->getUrl(); Assert::same(47832, $url->getPort()); - Assert::same('2001:db8:cafe::18', $url->getHost()); + Assert::same('[2001:db8:cafe::18]', $url->getHost()); });