Skip to content

Commit

Permalink
feat: 允许覆盖原有的客户端ip提取逻辑
Browse files Browse the repository at this point in the history
  • Loading branch information
hsldymq committed Oct 18, 2022
1 parent 0b9aefc commit a61f382
Show file tree
Hide file tree
Showing 6 changed files with 131 additions and 1 deletion.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
vendor/*
.idea/
composer.lock
3 changes: 3 additions & 0 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@
"psr/http-message": "^1.0",
"yeaha/owl-core": "1.0.*"
},
"require-dev": {
"phpunit/phpunit": "^5.6"
},
"autoload": {
"psr-4": {
"Owl\\Context\\": "src/Context/",
Expand Down
5 changes: 5 additions & 0 deletions phpunit.xml
Original file line number Diff line number Diff line change
@@ -1,2 +1,7 @@
<phpunit bootstrap="./tests/BootStrap.php" colors="true">
<testsuites>
<testsuite name="MVC">
<directory suffix="Test.php">./tests</directory>
</testsuite>
</testsuites>
</phpunit>
17 changes: 17 additions & 0 deletions src/Http/Request.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ class Request implements ServerRequestInterface
{
use \Owl\Http\MessageTrait;

/** @var callable */
private $client_ip_extractor = null;

protected $get;
protected $post;
protected $cookies;
Expand Down Expand Up @@ -371,11 +374,25 @@ public function disallowClientProxyIP()
$this->allow_client_proxy_ip = false;
}

/**
* @param callable $func
*
* @return void
*/
public function setClientIpExtractor($func)
{
$this->client_ip_extractor = $func;
}

/**
* @return string
*/
public function getClientIP()
{
if ($this->client_ip_extractor) {
return call_user_func($this->client_ip_extractor, $this, $this->allow_client_proxy_ip);
}

if (!$this->allow_client_proxy_ip || !($ip = $this->getServerParam('http_x_forwarded_for'))) {
return $this->getServerParam('remote_addr');
}
Expand Down
104 changes: 104 additions & 0 deletions tests/Http/RequestTest.php
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
<?php
namespace Tests\Http;

use Owl\Http\Request;

class RequestTest extends \PHPUnit_Framework_TestCase
{
public function testGet()
Expand Down Expand Up @@ -162,5 +164,107 @@ public function testGetIP()

$request->allowClientProxyIP();
$this->assertEquals('192.168.1.2', $request->getClientIP());

// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

$ip_extractor = function($request, $allow_client_proxy_ip) {
/**
* @var Request $request
* @var bool $allow_client_proxy_ip
*/
if ($clientIp = $request->getHeaderLine('x-real-client-ip')) {
return $clientIp;
}

if ($xrip = $request->getHeaderLine('X-Real-IP')) {
return $xrip;
}

if (!$allow_client_proxy_ip || !($ip = $request->getServerParam('http_x_forwarded_for'))) {
return $request->getServerParam('remote_addr');
}

if (false === strpos($ip, ',')) {
return $ip;
}

// private ip range, ip2long()
$private = [
[0, 50331647], // 0.0.0.0, 2.255.255.255
[167772160, 184549375], // 10.0.0.0, 10.255.255.255
[2130706432, 2147483647], // 127.0.0.0, 127.255.255.255
[2851995648, 2852061183], // 169.254.0.0, 169.254.255.255
[2886729728, 2887778303], // 172.16.0.0, 172.31.255.255
[3221225984, 3221226239], // 192.0.2.0, 192.0.2.255
[3232235520, 3232301055], // 192.168.0.0, 192.168.255.255
[4294967040, 4294967295], // 255.255.255.0 255.255.255.255
];

$ip_set = array_map('trim', explode(',', $ip));

// 检查是否私有地址,如果不是就直接返回
foreach ($ip_set as $key => $ip) {
$long = ip2long($ip);

if (false === $long) {
unset($ip_set[$key]);
continue;
}

$is_private = false;

foreach ($private as $m) {
list($min, $max) = $m;
if ($long >= $min && $long <= $max) {
$is_private = true;
break;
}
}

if (!$is_private) {
return $ip;
}
}

return array_shift($ip_set) ?: '0.0.0.0';
};
$request = \Owl\Http\Request::factory([
'uri' => '/',
'method' => 'GET',
'cookies' => [],
'headers' => [
"x-hc-date" => "2022-10-16T19:17:14.99672+08:00","via" => "cn1575.l1, l2su121-6.l2, l2st3-1.l2",
"x-forwarded-for" => "60.205.218.181, 119.23.91.192, 127.0.0.1",
"ali-cdn-real-ip" => "60.205.218.181",
"content-type" => "application/x-www-form-urlencoded",
"x-alicdn-da-via" => "47.105.29.104,59.36.94.249,119.23.91.244",
"x-real-client-ip" => "42.2.87.59",
],
'get' => [],
'post' => [],
'ip' => '',
'_SERVER' => [],
]);
$request->setClientIpExtractor($ip_extractor);
$request->allowClientProxyIP();
$this->assertEquals('42.2.87.59', $request->getClientIP());

// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
$request = \Owl\Http\Request::factory([
'uri' => '/',
'method' => 'GET',
'cookies' => [],
'headers' => [],
'get' => [],
'post' => [],
'ip' => '',
'_SERVER' => [
'REMOTE_ADDR' => '127.0.0.1',
'HTTP_X_FORWARDED_FOR' => '192.168.1.2,192.168.1.3',
],
]);
$request->setClientIpExtractor($ip_extractor);
$request->allowClientProxyIP();
$this->assertEquals('192.168.1.2', $request->getClientIP());
}
}
2 changes: 1 addition & 1 deletion tests/Mvc/RouterTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ public function testDispatchBasePath()
$this->assertSame(['\Controller\Foo\Bar', []], $router->testDispatch('/foobar/foo/bar'));
$this->assertSame(['\Controller\Baz', []], $router->testDispatch('/foobar/baz'));

$this->setExpectedException('\Owl\Http\Exception', '', 404);
$this->expectException('\Owl\Http\Exception');
$router->testDispatch('/baz');
}

Expand Down

0 comments on commit a61f382

Please sign in to comment.