Skip to content

Commit 72ed572

Browse files
luxin88houzhouyanglimingxinleo
authored
Support parsing IPv6 host. (#5052)
Co-authored-by: houzhouyang <810921248@qq.com> Co-authored-by: 李铭昕 <715557344@qq.com>
1 parent f64a2aa commit 72ed572

File tree

2 files changed

+80
-11
lines changed

2 files changed

+80
-11
lines changed

src/Server/Request.php

100755100644
Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -543,25 +543,21 @@ private static function getUriFromGlobals(Swoole\Http\Request $swooleRequest): U
543543

544544
$hasPort = false;
545545
if (isset($server['http_host'])) {
546-
$hostHeaderParts = explode(':', $server['http_host']);
547-
$uri = $uri->withHost($hostHeaderParts[0]);
548-
if (isset($hostHeaderParts[1])) {
546+
[$host, $port] = self::parseHost($server['http_host']);
547+
$uri = $uri->withHost($host);
548+
if (isset($port)) {
549549
$hasPort = true;
550-
$uri = $uri->withPort($hostHeaderParts[1]);
550+
$uri = $uri->withPort($port);
551551
}
552552
} elseif (isset($server['server_name'])) {
553553
$uri = $uri->withHost($server['server_name']);
554554
} elseif (isset($server['server_addr'])) {
555555
$uri = $uri->withHost($server['server_addr']);
556556
} elseif (isset($header['host'])) {
557557
$hasPort = true;
558-
if (\strpos($header['host'], ':')) {
559-
[$host, $port] = explode(':', $header['host'], 2);
560-
if ($port != $uri->getDefaultPort()) {
561-
$uri = $uri->withPort($port);
562-
}
563-
} else {
564-
$host = $header['host'];
558+
[$host, $port] = self::parseHost($header['host']);
559+
if (isset($port) && $port !== $uri->getDefaultPort()) {
560+
$uri = $uri->withPort($port);
565561
}
566562

567563
$uri = $uri->withHost($host);
@@ -587,4 +583,14 @@ private static function getUriFromGlobals(Swoole\Http\Request $swooleRequest): U
587583

588584
return $uri;
589585
}
586+
587+
/**
588+
* Get host parts, support ipv6.
589+
*/
590+
private static function parseHost(string $httpHost): array
591+
{
592+
$parts = parse_url('//' . $httpHost);
593+
594+
return [$parts['host'], $parts['port'] ?? null];
595+
}
590596
}

tests/ServerRequestTest.php

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
use PHPUnit\Framework\TestCase;
2727
use Psr\Container\ContainerInterface;
2828
use Psr\Http\Message\RequestInterface;
29+
use ReflectionClass;
2930
use Swoole\Http\Request as SwooleRequest;
3031

3132
/**
@@ -155,6 +156,68 @@ public function testGetUriFromGlobals()
155156
$this->assertSame(null, $uri->getPort());
156157
}
157158

159+
/**
160+
* @group ParseHost
161+
*/
162+
public function testParseHost()
163+
{
164+
$hostStrIPv4 = '192.168.119.100:9501';
165+
$hostStrIPv6 = '[fe80::a464:1aff:fe88:7b5a]:9502';
166+
$objReflectClass = new ReflectionClass('Hyperf\HttpMessage\Server\Request');
167+
$method = $objReflectClass->getMethod('parseHost');
168+
$method->setAccessible(true);
169+
170+
$resIPv4 = $method->invokeArgs(null, [$hostStrIPv4]);
171+
$this->assertSame('192.168.119.100', $resIPv4[0]);
172+
$this->assertSame(9501, $resIPv4[1]);
173+
174+
$resIPv6 = $method->invokeArgs(null, [$hostStrIPv6]);
175+
$this->assertSame('[fe80::a464:1aff:fe88:7b5a]', $resIPv6[0]);
176+
$this->assertSame(9502, $resIPv6[1]);
177+
}
178+
179+
/**
180+
* @dataProvider getIPv6Examples
181+
* @param mixed $originHost
182+
* @param mixed $host
183+
* @param mixed $port
184+
*/
185+
public function testGetUriFromGlobalsForIPv6Host($originHost, $host, $port)
186+
{
187+
$swooleRequest = Mockery::mock(SwooleRequest::class);
188+
$data = ['name' => 'Hyperf'];
189+
$swooleRequest->shouldReceive('rawContent')->andReturn(Json::encode($data));
190+
191+
$swooleRequest->server = [
192+
'http_host' => $originHost,
193+
];
194+
$request = Request::loadFromSwooleRequest($swooleRequest);
195+
$uri = $request->getUri();
196+
$this->assertSame($port, $uri->getPort());
197+
$this->assertSame($host, $uri->getHost());
198+
199+
$swooleRequest->server = [];
200+
$swooleRequest->header = [
201+
'host' => $originHost,
202+
];
203+
$request = Request::loadFromSwooleRequest($swooleRequest);
204+
$uri = $request->getUri();
205+
$this->assertSame($port, $uri->getPort());
206+
$this->assertSame($host, $uri->getHost());
207+
}
208+
209+
public function getIPv6Examples(): array
210+
{
211+
return [
212+
['localhost:9501', 'localhost', 9501],
213+
['localhost:', 'localhost', null],
214+
['localhost', 'localhost', null],
215+
['[2a00:f48:1008::212:183:10]', '[2a00:f48:1008::212:183:10]', null],
216+
['[2a00:f48:1008::212:183:10]:9501', '[2a00:f48:1008::212:183:10]', 9501],
217+
['[2a00:f48:1008::212:183:10]:', '[2a00:f48:1008::212:183:10]', null],
218+
];
219+
}
220+
158221
protected function getContainer()
159222
{
160223
$container = Mockery::mock(ContainerInterface::class);

0 commit comments

Comments
 (0)