Page MenuHomeDevCentral

No OneTemporary

diff --git a/src/HTTP/Requests/RemoteAddress.php b/src/HTTP/Requests/RemoteAddress.php
index 19bc653..eb2a5fe 100644
--- a/src/HTTP/Requests/RemoteAddress.php
+++ b/src/HTTP/Requests/RemoteAddress.php
@@ -1,87 +1,83 @@
<?php
declare(strict_types=1);
namespace Keruald\OmniTools\HTTP\Requests;
class RemoteAddress {
/**
* @var string
*/
private $remoteAddress;
///
/// Constructor
///
public function __construct (string $remoteAddress = '') {
$this->remoteAddress = $remoteAddress;
}
public static function fromServer () : self {
return new self(self::extractRemoteAddressesFromHeaders());
}
///
/// Format methods
///
public function has () : bool {
return $this->remoteAddress !== "";
}
public function getClientAddress () : string {
- if (strpos($this->remoteAddress, ',') === false) {
- // We only have one value, it's the IP
- return $this->remoteAddress;
- }
-
// Header contains 'clientIP, proxyIP, anotherProxyIP'
+ // or 'clientIP proxyIP anotherProxyIP'
// The first value is so the one to return.
// See draft-ietf-appsawg-http-forwarded-10.
- $ips = explode(',', $this->remoteAddress, 2);
+ $ips = preg_split("/[\s,]+/", $this->remoteAddress, 2);
return trim($ips[0]);
}
public function getAll () : string {
return $this->remoteAddress;
}
///
/// Helper methods to determine the remote address
///
/**
* Allows to get all the remote addresses from relevant headers
*/
public static function extractRemoteAddressesFromHeaders () : string {
foreach (self::listRemoteAddressHeaders() as $candidate) {
if (isset($_SERVER[$candidate])) {
return $_SERVER[$candidate];
}
}
return "";
}
///
/// Data sources
///
public static function listRemoteAddressHeaders () : array {
return [
// Standard header provided by draft-ietf-appsawg-http-forwarded-10
'HTTP_X_FORWARDED_FOR',
// Legacy headers
'HTTP_CLIENT_IP',
'HTTP_FORWARDED',
'HTTP_FORWARDED_FOR',
'HTTP_X_CLUSTER_CLIENT_IP',
'HTTP_X_FORWARDED',
// Default header if no proxy information could be detected
'REMOTE_ADDR',
];
}
}
diff --git a/tests/HTTP/Requests/RequestTest.php b/tests/HTTP/Requests/RequestTest.php
index 95d448c..4cf958f 100644
--- a/tests/HTTP/Requests/RequestTest.php
+++ b/tests/HTTP/Requests/RequestTest.php
@@ -1,117 +1,137 @@
<?php
declare(strict_types=1);
namespace Keruald\OmniTools\Tests\HTTP\Requests;
use Keruald\OmniTools\HTTP\Requests\Request;
use PHPUnit\Framework\TestCase;
class RequestTest extends TestCase {
///
/// Tests
///
/**
* @covers \Keruald\OmniTools\HTTP\Requests\Request::getRemoteAddress
* @backupGlobals enabled
*/
public function testGetRemoteAddress () : void {
$this->assertEmpty(Request::getRemoteAddress());
$_SERVER = [
'REMOTE_ADDR' => '10.0.0.2',
];
$this->assertEquals('10.0.0.2', Request::getRemoteAddress());
$_SERVER += [
'HTTP_X_FORWARDED_FOR' => '10.0.0.3',
'HTTP_CLIENT_IP' => '10.0.0.4',
];
$this->assertEquals(
'10.0.0.3', Request::getRemoteAddress(),
"HTTP_X_FORWARDED_FOR must be prioritized."
);
}
+ /**
+ * @covers \Keruald\OmniTools\HTTP\Requests\Request::getClientAddress
+ * @backupGlobals enabled
+ */
+ public function testGetRemoteAddressWithSeveralAddresses () : void {
+ $_SERVER = [
+ 'HTTP_X_FORWARDED_FOR' => '10.0.0.2 10.0.0.3',
+ ];
+ $this->assertEquals('10.0.0.2', Request::getRemoteAddress(),
+ "HTTP_X_FORWARDED_FOR could contain more than one address, the client one is the first"
+ );
+
+ $_SERVER = [
+ 'HTTP_X_FORWARDED_FOR' => '10.0.0.2, 10.0.0.3',
+ ];
+ $this->assertEquals('10.0.0.2', Request::getRemoteAddress(),
+ "HTTP_X_FORWARDED_FOR could contain more than one address, the client one is the first"
+ );
+ }
+
/**
* @covers \Keruald\OmniTools\HTTP\Requests\Request::getAcceptedLanguages
* @backupGlobals enabled
*/
public function testGetAcceptedLanguages () : void {
$_SERVER = [
'HTTP_ACCEPT_LANGUAGE' => 'fr,en-US;q=0.7,en;q=0.3',
];
$this->assertEquals(
["fr", "en-US", "en"],
Request::getAcceptedLanguages()
);
}
/**
* @backupGlobals enabled
* @dataProvider provideServerURLs
*/
public function testGetServerURL (array $server, string $url) : void {
$_SERVER = $server;
$this->assertEquals($url, Request::getServerURL());
}
///
/// Data providers
///
public function provideServerURLs () : iterable {
yield [[], "http://localhost"];
yield [["UNRELATED" => "ANYTHING"], "http://localhost"];
yield [
[
"SERVER_PORT" => "80",
"SERVER_NAME" => "acme.tld",
],
"http://acme.tld"
];
yield [
[
"SERVER_PORT" => "443",
"SERVER_NAME" => "acme.tld",
],
"https://acme.tld"
];
yield [
[
"SERVER_PORT" => "80",
"SERVER_NAME" => "acme.tld",
"HTTP_X_FORWARDED_PROTO" => "https",
],
"https://acme.tld"
];
yield [
[
"SERVER_PORT" => "80",
"SERVER_NAME" => "acme.tld",
"HTTP_FORWARDED" => "for=192.0.2.43, for=\"[2001:db8:cafe::17]\", proto=https, by=203.0.113.43",
],
"https://acme.tld"
];
yield [
[
"SERVER_PORT" => "8443",
"SERVER_NAME" => "acme.tld",
"HTTPS" => "on",
],
"https://acme.tld:8443"
];
}
}

File Metadata

Mime Type
text/x-diff
Expires
Thu, Sep 18, 02:08 (1 d, 21 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
2987712
Default Alt Text
(6 KB)

Event Timeline