Skip to content

Commit

Permalink
Support parsing IPv6 host. (#5052)
Browse files Browse the repository at this point in the history
Co-authored-by: houzhouyang <810921248@qq.com>
Co-authored-by: 李铭昕 <715557344@qq.com>
  • Loading branch information
3 people authored Aug 24, 2022
1 parent f64a2aa commit 72ed572
Show file tree
Hide file tree
Showing 2 changed files with 80 additions and 11 deletions.
28 changes: 17 additions & 11 deletions src/Server/Request.php
100755 → 100644
Original file line number Diff line number Diff line change
Expand Up @@ -543,25 +543,21 @@ private static function getUriFromGlobals(Swoole\Http\Request $swooleRequest): U

$hasPort = false;
if (isset($server['http_host'])) {
$hostHeaderParts = explode(':', $server['http_host']);
$uri = $uri->withHost($hostHeaderParts[0]);
if (isset($hostHeaderParts[1])) {
[$host, $port] = self::parseHost($server['http_host']);
$uri = $uri->withHost($host);
if (isset($port)) {
$hasPort = true;
$uri = $uri->withPort($hostHeaderParts[1]);
$uri = $uri->withPort($port);
}
} elseif (isset($server['server_name'])) {
$uri = $uri->withHost($server['server_name']);
} elseif (isset($server['server_addr'])) {
$uri = $uri->withHost($server['server_addr']);
} elseif (isset($header['host'])) {
$hasPort = true;
if (\strpos($header['host'], ':')) {
[$host, $port] = explode(':', $header['host'], 2);
if ($port != $uri->getDefaultPort()) {
$uri = $uri->withPort($port);
}
} else {
$host = $header['host'];
[$host, $port] = self::parseHost($header['host']);
if (isset($port) && $port !== $uri->getDefaultPort()) {
$uri = $uri->withPort($port);
}

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

return $uri;
}

/**
* Get host parts, support ipv6.
*/
private static function parseHost(string $httpHost): array
{
$parts = parse_url('//' . $httpHost);

return [$parts['host'], $parts['port'] ?? null];
}
}
63 changes: 63 additions & 0 deletions tests/ServerRequestTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
use PHPUnit\Framework\TestCase;
use Psr\Container\ContainerInterface;
use Psr\Http\Message\RequestInterface;
use ReflectionClass;
use Swoole\Http\Request as SwooleRequest;

/**
Expand Down Expand Up @@ -155,6 +156,68 @@ public function testGetUriFromGlobals()
$this->assertSame(null, $uri->getPort());
}

/**
* @group ParseHost
*/
public function testParseHost()
{
$hostStrIPv4 = '192.168.119.100:9501';
$hostStrIPv6 = '[fe80::a464:1aff:fe88:7b5a]:9502';
$objReflectClass = new ReflectionClass('Hyperf\HttpMessage\Server\Request');
$method = $objReflectClass->getMethod('parseHost');
$method->setAccessible(true);

$resIPv4 = $method->invokeArgs(null, [$hostStrIPv4]);
$this->assertSame('192.168.119.100', $resIPv4[0]);
$this->assertSame(9501, $resIPv4[1]);

$resIPv6 = $method->invokeArgs(null, [$hostStrIPv6]);
$this->assertSame('[fe80::a464:1aff:fe88:7b5a]', $resIPv6[0]);
$this->assertSame(9502, $resIPv6[1]);
}

/**
* @dataProvider getIPv6Examples
* @param mixed $originHost
* @param mixed $host
* @param mixed $port
*/
public function testGetUriFromGlobalsForIPv6Host($originHost, $host, $port)
{
$swooleRequest = Mockery::mock(SwooleRequest::class);
$data = ['name' => 'Hyperf'];
$swooleRequest->shouldReceive('rawContent')->andReturn(Json::encode($data));

$swooleRequest->server = [
'http_host' => $originHost,
];
$request = Request::loadFromSwooleRequest($swooleRequest);
$uri = $request->getUri();
$this->assertSame($port, $uri->getPort());
$this->assertSame($host, $uri->getHost());

$swooleRequest->server = [];
$swooleRequest->header = [
'host' => $originHost,
];
$request = Request::loadFromSwooleRequest($swooleRequest);
$uri = $request->getUri();
$this->assertSame($port, $uri->getPort());
$this->assertSame($host, $uri->getHost());
}

public function getIPv6Examples(): array
{
return [
['localhost:9501', 'localhost', 9501],
['localhost:', 'localhost', null],
['localhost', 'localhost', null],
['[2a00:f48:1008::212:183:10]', '[2a00:f48:1008::212:183:10]', null],
['[2a00:f48:1008::212:183:10]:9501', '[2a00:f48:1008::212:183:10]', 9501],
['[2a00:f48:1008::212:183:10]:', '[2a00:f48:1008::212:183:10]', null],
];
}

protected function getContainer()
{
$container = Mockery::mock(ContainerInterface::class);
Expand Down

0 comments on commit 72ed572

Please sign in to comment.