From e6182097f4a9005de69f34f82c3f76b5c6162473 Mon Sep 17 00:00:00 2001 From: Sam <8619576+samjf@users.noreply.github.com> Date: Mon, 11 Apr 2022 21:32:52 +1200 Subject: Add the request hostname to error & exception logs (#18996) * Add the hostname to the tracker exception log so multi-tenant domains are easier to debug * Add hostname to error log to help with debugging * use Url::getHost and add method to Url class instead * apply PSR12 code formatting Co-authored-by: sgiehl --- tests/PHPUnit/Unit/UrlTest.php | 350 +++++++++++++++++++++-------------------- 1 file changed, 180 insertions(+), 170 deletions(-) (limited to 'tests/PHPUnit') diff --git a/tests/PHPUnit/Unit/UrlTest.php b/tests/PHPUnit/Unit/UrlTest.php index 336eff2757..c6a7bc82a4 100644 --- a/tests/PHPUnit/Unit/UrlTest.php +++ b/tests/PHPUnit/Unit/UrlTest.php @@ -1,4 +1,5 @@ assertEquals(Url::getCurrentQueryStringWithParametersModified(array()), Url::getCurrentQueryString()); + $this->assertEquals(Url::getCurrentQueryStringWithParametersModified([]), Url::getCurrentQueryString()); $this->assertEquals(Url::getCurrentUrl(), Url::getCurrentUrlWithoutQueryString()); $this->assertEquals(Url::getCurrentUrl(), Url::getCurrentScheme() . '://' . Url::getCurrentHost() . Url::getCurrentScriptName()); $_SERVER['QUERY_STRING'] = 'q=test'; $parameters = array_keys(Url::getArrayFromCurrentQueryString()); - $parametersNameToValue = array(); + $parametersNameToValue = []; foreach ($parameters as $name) { $parametersNameToValue[$name] = null; } @@ -39,25 +40,25 @@ class UrlTest extends \PHPUnit\Framework\TestCase */ public function getCurrentHosts() { - return array( - array('localhost IPv4', array('127.0.0.1', null, null, null, '127.0.0.1')), - array('localhost IPv6', array('[::1]', null, null, null, '[::1]')), - array('localhost name', array('localhost', null, null, null, 'localhost')), - - array('IPv4 without proxy', array('128.1.2.3', null, null, null, '128.1.2.3')), - array('IPv6 without proxy', array('[2001::b0b]', null, null, null, '[2001::b0b]')), - array('name without proxy', array('example.com', null, null, null, 'example.com')), - - array('IPv4 with one proxy', array('127.0.0.1', '128.1.2.3', 'HTTP_X_FORWARDED_HOST', null, '128.1.2.3')), - array('IPv6 with one proxy', array('[::1]', '[2001::b0b]', 'HTTP_X_FORWARDED_HOST', null, '[2001::b0b]')), - array('name with one IPv4 proxy', array('192.168.1.10', 'example.com', 'HTTP_X_FORWARDED_HOST', null, 'example.com')), - array('name with one IPv6 proxy', array('[::10]', 'www.example.com', 'HTTP_X_FORWARDED_HOST', null, 'www.example.com')), - array('name with one named proxy', array('dmz.example.com', 'www.example.com', 'HTTP_X_FORWARDED_HOST', null, 'www.example.com')), - - array('IPv4 with multiple proxies', array('127.0.0.1', '128.1.2.3, 192.168.1.10', 'HTTP_X_FORWARDED_HOST', '192.168.1.*', '128.1.2.3')), - array('IPv6 with multiple proxies', array('[::1]', '[2001::b0b], [::ffff:192.168.1.10]', 'HTTP_X_FORWARDED_HOST', '::ffff:192.168.1.0/124', '[2001::b0b]')), - array('name with multiple proxies', array('dmz.example.com', 'www.example.com, dmz.example.com', 'HTTP_X_FORWARDED_HOST', 'dmz.example.com', 'www.example.com')), - ); + return [ + ['localhost IPv4', ['127.0.0.1', null, null, null, '127.0.0.1']], + ['localhost IPv6', ['[::1]', null, null, null, '[::1]']], + ['localhost name', ['localhost', null, null, null, 'localhost']], + + ['IPv4 without proxy', ['128.1.2.3', null, null, null, '128.1.2.3']], + ['IPv6 without proxy', ['[2001::b0b]', null, null, null, '[2001::b0b]']], + ['name without proxy', ['example.com', null, null, null, 'example.com']], + + ['IPv4 with one proxy', ['127.0.0.1', '128.1.2.3', 'HTTP_X_FORWARDED_HOST', null, '128.1.2.3']], + ['IPv6 with one proxy', ['[::1]', '[2001::b0b]', 'HTTP_X_FORWARDED_HOST', null, '[2001::b0b]']], + ['name with one IPv4 proxy', ['192.168.1.10', 'example.com', 'HTTP_X_FORWARDED_HOST', null, 'example.com']], + ['name with one IPv6 proxy', ['[::10]', 'www.example.com', 'HTTP_X_FORWARDED_HOST', null, 'www.example.com']], + ['name with one named proxy', ['dmz.example.com', 'www.example.com', 'HTTP_X_FORWARDED_HOST', null, 'www.example.com']], + + ['IPv4 with multiple proxies', ['127.0.0.1', '128.1.2.3, 192.168.1.10', 'HTTP_X_FORWARDED_HOST', '192.168.1.*', '128.1.2.3']], + ['IPv6 with multiple proxies', ['[::1]', '[2001::b0b], [::ffff:192.168.1.10]', 'HTTP_X_FORWARDED_HOST', '::ffff:192.168.1.0/124', '[2001::b0b]']], + ['name with multiple proxies', ['dmz.example.com', 'www.example.com, dmz.example.com', 'HTTP_X_FORWARDED_HOST', 'dmz.example.com', 'www.example.com']], + ]; } /** @@ -67,8 +68,8 @@ class UrlTest extends \PHPUnit\Framework\TestCase { Url::setHost($test[0]); $_SERVER['HTTP_X_FORWARDED_HOST'] = $test[1]; - Config::getInstance()->General['proxy_host_headers'] = array($test[2]); - Config::getInstance()->General['proxy_ips'] = array($test[3]); + Config::getInstance()->General['proxy_host_headers'] = [$test[2]]; + Config::getInstance()->General['proxy_ips'] = [$test[3]]; Config::getInstance()->General['enable_trusted_host_check'] = 0; $this->assertEquals($test[4], Url::getCurrentHost(), $description); } @@ -76,7 +77,7 @@ class UrlTest extends \PHPUnit\Framework\TestCase /** * @dataProvider getProtocol */ - public function test_getCurrentScheme_ProtoHeaderShouldPrecedenceHttpsHeader($proto) + public function testGetCurrentSchemeProtoHeaderShouldPrecedenceHttpsHeader($proto) { $_SERVER['HTTPS'] = 'on'; $_SERVER['HTTP_X_FORWARDED_PROTO'] = $proto; @@ -89,7 +90,7 @@ class UrlTest extends \PHPUnit\Framework\TestCase /** * @dataProvider getProtocol */ - public function test_getCurrentScheme_shouldDetectSecureFromHttpsHeader() + public function testGetCurrentSchemeShouldDetectSecureFromHttpsHeader() { $_SERVER['HTTPS'] = 'on'; $this->assertEquals('https', Url::getCurrentScheme()); @@ -100,14 +101,14 @@ class UrlTest extends \PHPUnit\Framework\TestCase /** * @dataProvider getProtocol */ - public function test_getCurrentScheme_shouldBeHttpByDefault() + public function testGetCurrentSchemeShouldBeHttpByDefault() { $this->assertEquals('http', Url::getCurrentScheme()); } public function getProtocol() { - return array(array('http'), array('https')); + return [['http'], ['https']]; } /** @@ -115,86 +116,86 @@ class UrlTest extends \PHPUnit\Framework\TestCase */ public function getLocalUrls() { - return array( + return [ // simple cases - array('www.example.com', 'http://www.example.com/path/index.php', '/path/index.php', 'http://www.example.com/path/index.php', true), - array('www.example.com', 'http://www.example.com/path/index.php?module=X', '/path/index.php', 'http://www.example.com/path/', true), - array('www.example.com', 'http://www.example.com/path/', '/path/index.php', 'http://www.example.com/path/index.php?module=Y', true), - array('www.example.com', 'http://www.example.com/path/#anchor', '/path/index.php', 'http://www.example.com/path/?query', true), - array('localhost:8080', 'http://localhost:8080/path/index.php', '/path/index.php', 'http://localhost:8080/path/index.php', true), - array('www.example.com', 'http://www.example.com/path/', '/path/', 'http://www.example.com/path2/', true), + ['www.example.com', 'http://www.example.com/path/index.php', '/path/index.php', 'http://www.example.com/path/index.php', true], + ['www.example.com', 'http://www.example.com/path/index.php?module=X', '/path/index.php', 'http://www.example.com/path/', true], + ['www.example.com', 'http://www.example.com/path/', '/path/index.php', 'http://www.example.com/path/index.php?module=Y', true], + ['www.example.com', 'http://www.example.com/path/#anchor', '/path/index.php', 'http://www.example.com/path/?query', true], + ['localhost:8080', 'http://localhost:8080/path/index.php', '/path/index.php', 'http://localhost:8080/path/index.php', true], + ['www.example.com', 'http://www.example.com/path/', '/path/', 'http://www.example.com/path2/', true], // ignore port - array('www.example.com', 'http://www.example.com:80/path/index.php', '/path/index.php', 'http://www.example.com/path/index.php', true), - array('www.example.com', 'http://www.example.com/path/index.php', '/path/index.php', 'http://www.example.com:80/path/index.php', true), + ['www.example.com', 'http://www.example.com:80/path/index.php', '/path/index.php', 'http://www.example.com/path/index.php', true], + ['www.example.com', 'http://www.example.com/path/index.php', '/path/index.php', 'http://www.example.com:80/path/index.php', true], - array('localhost', 'http://localhost:8080/path/index.php', '/path/index.php', 'http://localhost:8080/path/index.php', true), - array('localhost', 'http://localhost/path/index.php', '/path/index.php', 'http://localhost:8080/path/index.php', true), - array('localhost', 'http://localhost:8080/path/index.php', '/path/index.php', 'http://localhost/path/index.php', true), + ['localhost', 'http://localhost:8080/path/index.php', '/path/index.php', 'http://localhost:8080/path/index.php', true], + ['localhost', 'http://localhost/path/index.php', '/path/index.php', 'http://localhost:8080/path/index.php', true], + ['localhost', 'http://localhost:8080/path/index.php', '/path/index.php', 'http://localhost/path/index.php', true], - array('localhost:8080', 'http://localhost/path/index.php', '/path/index.php', 'http://localhost:8080/path/index.php', true), - array('localhost:8080', 'http://localhost:8080/path/index.php', '/path/index.php', 'http://localhost/path/index.php', true), - array('localhost:8080', 'http://localhost/path/index.php', '/path/index.php', 'http://localhost/path/index.php', true), - array('localhost:8080', 'http://localhost:8080/path/index.php', '/path/index.php', 'http://localhost:8080/path/index.php', true), + ['localhost:8080', 'http://localhost/path/index.php', '/path/index.php', 'http://localhost:8080/path/index.php', true], + ['localhost:8080', 'http://localhost:8080/path/index.php', '/path/index.php', 'http://localhost/path/index.php', true], + ['localhost:8080', 'http://localhost/path/index.php', '/path/index.php', 'http://localhost/path/index.php', true], + ['localhost:8080', 'http://localhost:8080/path/index.php', '/path/index.php', 'http://localhost:8080/path/index.php', true], // IPv6 - array('[::1]', 'http://[::1]/path/index.php', '/path/index.php', 'http://[::1]/path/index.php', true), - array('[::1]:8080', 'http://[::1]:8080/path/index.php', '/path/index.php', 'http://[::1]/path/index.php', true), - array('[::1]:8080', 'http://[::1]/path/index.php', '/path/index.php', 'http://[::1]:8080/path/index.php', true), + ['[::1]', 'http://[::1]/path/index.php', '/path/index.php', 'http://[::1]/path/index.php', true], + ['[::1]:8080', 'http://[::1]:8080/path/index.php', '/path/index.php', 'http://[::1]/path/index.php', true], + ['[::1]:8080', 'http://[::1]/path/index.php', '/path/index.php', 'http://[::1]:8080/path/index.php', true], // undefined SCRIPT URI - array('www.example.com', null, '/path/index.php', 'http://www.example.com/path/index.php', true), - array('localhost:8080', null, '/path/index.php', 'http://localhost:8080/path/index.php', true), - array('127.0.0.1:8080', null, '/path/index.php', 'http://127.0.0.1:8080/path/index.php', true), - array('[::1]', null, '/path/index.php', 'http://[::1]/path/index.php', true), - array('[::1]:8080', null, '/path/index.php', 'http://[::1]:8080/path/index.php', true), + ['www.example.com', null, '/path/index.php', 'http://www.example.com/path/index.php', true], + ['localhost:8080', null, '/path/index.php', 'http://localhost:8080/path/index.php', true], + ['127.0.0.1:8080', null, '/path/index.php', 'http://127.0.0.1:8080/path/index.php', true], + ['[::1]', null, '/path/index.php', 'http://[::1]/path/index.php', true], + ['[::1]:8080', null, '/path/index.php', 'http://[::1]:8080/path/index.php', true], // Apache+Rails anomaly in SCRIPT_URI - array('www.example.com', 'http://www.example.com/path/#anchor', 'http://www.example.com/path/index.php', 'http://www.example.com/path/?query', true), + ['www.example.com', 'http://www.example.com/path/#anchor', 'http://www.example.com/path/index.php', 'http://www.example.com/path/?query', true], // mangled HTTP_HOST - array('www.example.com', 'http://example.com/path/#anchor', '/path/index.php', 'http://example.com/path/referrer', true), + ['www.example.com', 'http://example.com/path/#anchor', '/path/index.php', 'http://example.com/path/referrer', true], // suppressed Referrer - array('www.example.com', 'http://www.example.com/path/#anchor', '/path/index.php', null, true), - array('www.example.com', 'http://www.example.com/path/#anchor', '/path/index.php', '', true), + ['www.example.com', 'http://www.example.com/path/#anchor', '/path/index.php', null, true], + ['www.example.com', 'http://www.example.com/path/#anchor', '/path/index.php', '', true], // mismatched scheme or host - array('www.example.com', 'http://www.example.com/path/?module=X', '/path/index.php', 'ftp://www.example.com/path/index.php', false), - array('www.example.com', 'http://www.example.com/path/?module=X', '/path/index.php', 'http://example.com/path/index.php', false), - array('www.example.com', 'http://www.example.com/path/', '/path/', 'http://crsf.example.com/path/', false), - ); + ['www.example.com', 'http://www.example.com/path/?module=X', '/path/index.php', 'ftp://www.example.com/path/index.php', false], + ['www.example.com', 'http://www.example.com/path/?module=X', '/path/index.php', 'http://example.com/path/index.php', false], + ['www.example.com', 'http://www.example.com/path/', '/path/', 'http://crsf.example.com/path/', false], + ]; } /** * @dataProvider getIsLocalHost */ - public function test_isLocalHost($expectedIsLocal, $host) + public function testIsLocalHost($expectedIsLocal, $host) { $this->assertSame($expectedIsLocal, Url::isLocalHost($host)); } public function getIsLocalHost() { - return array( - array($isLocal = false, '127.0.0.2'), - array($isLocal = false, '192.168.1.1'), - array($isLocal = false, '10.1.1.1'), - array($isLocal = false, '172.30.1.1'), + return [ + [$isLocal = false, '127.0.0.2'], + [$isLocal = false, '192.168.1.1'], + [$isLocal = false, '10.1.1.1'], + [$isLocal = false, '172.30.1.1'], - array($isLocal = true, 'localhost'), - array($isLocal = true, '127.0.0.1'), - array($isLocal = true, '::1'), - array($isLocal = true, '[::1]'), + [$isLocal = true, 'localhost'], + [$isLocal = true, '127.0.0.1'], + [$isLocal = true, '::1'], + [$isLocal = true, '[::1]'], // with port - array($isLocal = false, '172.30.1.1:80'), - array($isLocal = false, '3ffe:1900:4545:3:200:f8ff:fe21:67cf:1005'), - array($isLocal = true, 'localhost:3000'), - array($isLocal = true, '127.0.0.1:213424'), - array($isLocal = true, '::1:345'), - array($isLocal = true, '[::1]:443'), - ); + [$isLocal = false, '172.30.1.1:80'], + [$isLocal = false, '3ffe:1900:4545:3:200:f8ff:fe21:67cf:1005'], + [$isLocal = true, 'localhost:3000'], + [$isLocal = true, '127.0.0.1:213424'], + [$isLocal = true, '::1:345'], + [$isLocal = true, '[::1]:443'], + ]; } /** @@ -206,7 +207,7 @@ class UrlTest extends \PHPUnit\Framework\TestCase $_SERVER['SCRIPT_URI'] = $scripturi; $_SERVER['REQUEST_URI'] = $requesturi; Config::getInstance()->General['enable_trusted_host_check'] = 1; - Config::getInstance()->General['trusted_hosts'] = array($httphost); + Config::getInstance()->General['trusted_hosts'] = [$httphost]; $urlToTest = $testurl; $this->assertEquals($result, Url::isLocalUrl($urlToTest)); } @@ -216,12 +217,11 @@ class UrlTest extends \PHPUnit\Framework\TestCase */ public function getCurrentUrlWithoutFilename() { - return array( - array('http://example.com/', false, 'example.com', '/'), - array('https://example.org/', true, 'example.org', '/'), - array('https://example.net/piwik/', 'on', 'example.net', '/piwik/'), - ); - + return [ + ['http://example.com/', false, 'example.com', '/'], + ['https://example.org/', true, 'example.org', '/'], + ['https://example.net/piwik/', 'on', 'example.net', '/piwik/'], + ]; } /** @@ -240,26 +240,26 @@ class UrlTest extends \PHPUnit\Framework\TestCase $_SERVER['REQUEST_URI'] = $path; $_SERVER['HTTP_HOST'] = $host; - Config::getInstance()->General['trusted_hosts'] = array($host); + Config::getInstance()->General['trusted_hosts'] = [$host]; $url = Url::getCurrentUrlWithoutFilename(); $this->assertEquals($expected, $url); } - public function test_getCurrentScriptName() + public function testGetCurrentScriptName() { $this->resetGlobalVariables(); - $tests = array( - array('/', 'http://example.com/', null), - array('/', '/', null), - array('/index.php', '/index.php', null), - array('/index.php', '/index.php?module=Foo', null), - array('/index.php', '/index.php/route/1', '/route/1'), - array('/index.php', '/index.php# 'val'), 'key=val'), - array(array('key' => 'val', 'k2' => 'v2'), 'key=val&k2=v2'), - array(array('key' => 'val', 'k2' => false), 'key=val'), // remove false values - array(array('key' => 'val', 'k2' => null), 'key=val'), // remove null values - array(array('key' => 'val', 'k2' => array('v1', 'v2')), 'key=val&k2[]=v1&k2[]=v2'), - array(array('key' => 'val', 'k2' => array('k1' => 'v1', 'k2' => 'v2')), 'key=val&k2[]=v1&k2[]=v2'), - ); + return [ + [[], ''], + [['v1', 'v2'], '0=v1&1=v2'], + [['key' => 'val'], 'key=val'], + [['key' => 'val', 'k2' => 'v2'], 'key=val&k2=v2'], + [['key' => 'val', 'k2' => false], 'key=val'], // remove false values + [['key' => 'val', 'k2' => null], 'key=val'], // remove null values + [['key' => 'val', 'k2' => ['v1', 'v2']], 'key=val&k2[]=v1&k2[]=v2'], + [['key' => 'val', 'k2' => ['k1' => 'v1', 'k2' => 'v2']], 'key=val&k2[]=v1&k2[]=v2'], + ]; } /** @@ -346,15 +346,25 @@ class UrlTest extends \PHPUnit\Framework\TestCase public function getHostsFromUrl() { - return array( - array(null, null), - array('http://', null), - array('http://www.example.com', 'www.example.com'), - array('http://www.ExaMplE.cOm', 'www.example.com'), - array('http://www.example.com/test/foo?bar=xy', 'www.example.com'), - array('http://127.0.0.1', '127.0.0.1'), - array('example.com', null), - ); + return [ + [null, null], + ['http://', null], + ['http://www.example.com', 'www.example.com'], + ['http://www.ExaMplE.cOm', 'www.example.com'], + ['http://www.example.com/test/foo?bar=xy', 'www.example.com'], + ['http://127.0.0.1', '127.0.0.1'], + ['example.com', null], + ]; + } + + public function testGetRFCValidHostname() + { + $_SERVER['HTTP_HOST'] = 'demo.matomo.org'; + $this->assertEquals('demo.matomo.org', Url::getRFCValidHostname()); + unset($_SERVER['HTTP_HOST']); + $this->assertEquals('matomo.org', Url::getRFCValidHostname('matomo.org')); + $this->assertEquals(false, Url::getRFCValidHostname('matomo org')); + $this->assertEquals(false, Url::getRFCValidHostname('matomo.org;resetGlobalVariables(); // these variables where taken from a bug report - $_SERVER = array( + $_SERVER = [ 'QUERY_STRING' => 'foo=bar', 'PATH_INFO' => '/test.php', // Nginx passed a wrong value here (should be empty) 'SCRIPT_NAME' => '/test.php', @@ -453,7 +463,7 @@ class UrlTest extends \PHPUnit\Framework\TestCase 'SERVER_NAME' => 'example.com', 'HTTP_HOST' => 'example.com', 'PHP_SELF' => '/test.php/test.php', // Nginx passed a wrong value here (should be /test.php) - ); + ]; $expectedUrl = 'http://example.com/test.php?foo=bar'; @@ -462,8 +472,8 @@ class UrlTest extends \PHPUnit\Framework\TestCase private function resetGlobalVariables() { - $names = array('PATH_INFO', 'REQUEST_URI', 'SCRIPT_NAME', 'SCRIPT_FILENAME', 'argv', 'HTTPS', - 'HTTP_HOST', 'QUERY_STRING', 'HTTP_REFERER'); + $names = ['PATH_INFO', 'REQUEST_URI', 'SCRIPT_NAME', 'SCRIPT_FILENAME', 'argv', 'HTTPS', + 'HTTP_HOST', 'QUERY_STRING', 'HTTP_REFERER']; foreach ($names as $name) { unset($_SERVER[$name]); -- cgit v1.2.3