Skip to content

Commit

Permalink
Merge branch 'gboily-forwarded-rfc7239'
Browse files Browse the repository at this point in the history
Closes #3
  • Loading branch information
akrabat committed Nov 13, 2016
2 parents d45049c + 34f3593 commit 832687b
Show file tree
Hide file tree
Showing 2 changed files with 86 additions and 1 deletion.
28 changes: 27 additions & 1 deletion src/IpAddress.php
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ class IpAddress
* @var array
*/
protected $headersToInspect = [
'Forwarded',
'X-Forwarded-For',
'X-Forwarded',
'X-Cluster-Client-Ip',
Expand Down Expand Up @@ -117,7 +118,7 @@ protected function determineClientIpAddress($request)
if ($checkProxyHeaders) {
foreach ($this->headersToInspect as $header) {
if ($request->hasHeader($header)) {
$ip = trim(current(explode(',', $request->getHeaderLine($header))));
$ip = $this->getFirstIpAddressFromHeader($request, $header);
if ($this->isValidIpAddress($ip)) {
$ipAddress = $ip;
break;
Expand All @@ -143,4 +144,29 @@ protected function isValidIpAddress($ip)
}
return true;
}

/**
* Find out the client's IP address from the headers available to us
*
* @param ServerRequestInterface $request PSR-7 Request
* @param string $header Header name
* @return string
*/
private function getFirstIpAddressFromHeader($request, $header)
{
$items = explode(',', $request->getHeaderLine($header));
$headerValue = trim(reset($items));

if (ucfirst($header) == 'Forwarded') {
foreach (explode(';', $headerValue) as $headerPart) {
if (strtolower(substr($headerPart, 0, 4)) == 'for=') {
$for = explode(']', $headerPart);
$headerValue = trim(substr(reset($for), 4), " \t\n\r\0\x0B" . "\"[]");
break;
}
}
}

return $headerValue;
}
}
59 changes: 59 additions & 0 deletions tests/IpAddressTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,65 @@ public function testXForwardedForIpWithUntrustedProxy()
$this->assertSame('192.168.0.2', $ipAddress);
}

public function testForwardedWithMultipleFor()
{
$middleware = new IPAddress(true);

$request = ServerRequestFactory::fromGlobals([
'REMOTE_ADDR' => '192.168.1.1',
'HTTP_FORWARDED' => 'for=192.0.2.43, for=198.51.100.17;by=203.0.113.60;proto=http;host=example.com',
]);
$response = new Response();

$ipAddress = '123';
$response = $middleware($request, $response, function ($request, $response) use (&$ipAddress) {
// simply store the "ip_address" attribute in to the referenced $ipAddress
$ipAddress = $request->getAttribute('ip_address');
return $response;
});

$this->assertSame('192.0.2.43', $ipAddress);
}

public function testForwardedWithAllOptions()
{
$middleware = new IPAddress(true);

$request = ServerRequestFactory::fromGlobals([
'REMOTE_ADDR' => '192.168.1.1',
'HTTP_FORWARDED' => 'for=192.0.2.60; proto=http;by=203.0.113.43; host=_hiddenProxy, for=192.0.2.61',
]);
$response = new Response();

$ipAddress = '123';
$response = $middleware($request, $response, function ($request, $response) use (&$ipAddress) {
// simply store the "ip_address" attribute in to the referenced $ipAddress
$ipAddress = $request->getAttribute('ip_address');
return $response;
});

$this->assertSame('192.0.2.60', $ipAddress);
}

public function testForwardedWithWithIpV6()
{
$middleware = new IPAddress(true);

$request = ServerRequestFactory::fromGlobals([
'REMOTE_ADDR' => '192.168.1.1',
'HTTP_FORWARDED' => 'For="[2001:db8:cafe::17]:4711", for=_internalProxy',
]);
$response = new Response();

$ipAddress = '123';
$response = $middleware($request, $response, function ($request, $response) use (&$ipAddress) {
// simply store the "ip_address" attribute in to the referenced $ipAddress
$ipAddress = $request->getAttribute('ip_address');
return $response;
});

$this->assertSame('2001:db8:cafe::17', $ipAddress);
}

public function testCustomHeader()
{
Expand Down

0 comments on commit 832687b

Please sign in to comment.