From 9a14e6e84a4db96d43b3c5863fc2917855591881 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Tu=C5=BEil?= Date: Tue, 14 Nov 2023 12:55:44 -0500 Subject: [PATCH] RequestFactory: unify and fix host parsing (#229) Co-authored-by: David Grudl --- src/Http/RequestFactory.php | 51 +++++++++++-------- .../Http/RequestFactory.proxy.forwarded.phpt | 4 +- 2 files changed, 31 insertions(+), 24 deletions(-) diff --git a/src/Http/RequestFactory.php b/src/Http/RequestFactory.php index 56ad04bb..e3c3c41d 100644 --- a/src/Http/RequestFactory.php +++ b/src/Http/RequestFactory.php @@ -81,12 +81,12 @@ 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)); - } elseif ($tmp === 'SERVER_NAME' && isset($_SERVER['SERVER_PORT'])) { + $url->setHost($pair[0]); + if (isset($pair[1])) { + $url->setPort($pair[1]); + } elseif (isset($_SERVER['SERVER_PORT'])) { $url->setPort((int) $_SERVER['SERVER_PORT']); } } @@ -309,22 +309,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; @@ -365,7 +356,23 @@ private function useNonstandardProxy(Url $url): ?string } - /** @deprecated use fromGlobals() */ + /** + * @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 { trigger_error(__METHOD__ . '() is deprecated, use fromGlobals()', E_USER_DEPRECATED); diff --git a/tests/Http/RequestFactory.proxy.forwarded.phpt b/tests/Http/RequestFactory.proxy.forwarded.phpt index b8ed7851..801ac0f2 100644 --- a/tests/Http/RequestFactory.proxy.forwarded.phpt +++ b/tests/Http/RequestFactory.proxy.forwarded.phpt @@ -65,7 +65,7 @@ test('', function () { Assert::null(@$factory->fromGlobals()->getRemoteHost()); // deprecated $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()); });