Skip to content

Commit d05a040

Browse files
committed
Merge branch '6.3' into 6.4
* 6.3: [HttpFoundation] Fix base URI detection on IIS with UrlRewriteModule
2 parents 9b304fc + cac1556 commit d05a040

File tree

2 files changed

+83
-3
lines changed

2 files changed

+83
-3
lines changed

Request.php

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -239,6 +239,9 @@ class Request
239239
self::HEADER_X_FORWARDED_PREFIX => 'X_FORWARDED_PREFIX',
240240
];
241241

242+
/** @var bool */
243+
private $isIisRewrite = false;
244+
242245
/**
243246
* @param array $query The GET parameters
244247
* @param array $request The POST parameters
@@ -1747,11 +1750,10 @@ protected function prepareRequestUri()
17471750
{
17481751
$requestUri = '';
17491752

1750-
if ('1' == $this->server->get('IIS_WasUrlRewritten') && '' != $this->server->get('UNENCODED_URL')) {
1753+
if ($this->isIisRewrite() && '' != $this->server->get('UNENCODED_URL')) {
17511754
// IIS7 with URL Rewrite: make sure we get the unencoded URL (double slash problem)
17521755
$requestUri = $this->server->get('UNENCODED_URL');
17531756
$this->server->remove('UNENCODED_URL');
1754-
$this->server->remove('IIS_WasUrlRewritten');
17551757
} elseif ($this->server->has('REQUEST_URI')) {
17561758
$requestUri = $this->server->get('REQUEST_URI');
17571759

@@ -1950,7 +1952,13 @@ private function setPhpDefaultLocale(string $locale): void
19501952
*/
19511953
private function getUrlencodedPrefix(string $string, string $prefix): ?string
19521954
{
1953-
if (!str_starts_with(rawurldecode($string), $prefix)) {
1955+
if ($this->isIisRewrite()) {
1956+
// ISS with UrlRewriteModule might report SCRIPT_NAME/PHP_SELF with wrong case
1957+
// see https://github.com/php/php-src/issues/11981
1958+
if (0 !== stripos(rawurldecode($string), $prefix)) {
1959+
return null;
1960+
}
1961+
} elseif (!str_starts_with(rawurldecode($string), $prefix)) {
19541962
return null;
19551963
}
19561964

@@ -2079,4 +2087,20 @@ private function normalizeAndFilterClientIps(array $clientIps, string $ip): arra
20792087
// Now the IP chain contains only untrusted proxies and the client IP
20802088
return $clientIps ? array_reverse($clientIps) : [$firstTrustedIp];
20812089
}
2090+
2091+
/**
2092+
* Is this IIS with UrlRewriteModule?
2093+
*
2094+
* This method consumes, caches and removed the IIS_WasUrlRewritten env var,
2095+
* so we don't inherit it to sub-requests.
2096+
*/
2097+
private function isIisRewrite(): bool
2098+
{
2099+
if (1 === $this->server->getInt('IIS_WasUrlRewritten')) {
2100+
$this->isIisRewrite = true;
2101+
$this->server->remove('IIS_WasUrlRewritten');
2102+
}
2103+
2104+
return $this->isIisRewrite;
2105+
}
20822106
}

Tests/RequestTest.php

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1883,6 +1883,62 @@ public static function getBaseUrlData()
18831883
];
18841884
}
18851885

1886+
/**
1887+
* @dataProvider baseUriDetectionOnIisWithRewriteData
1888+
*/
1889+
public function testBaseUriDetectionOnIisWithRewrite(array $server, string $expectedBaseUrl, string $expectedPathInfo)
1890+
{
1891+
$request = new Request([], [], [], [], [], $server);
1892+
1893+
self::assertSame($expectedBaseUrl, $request->getBaseUrl());
1894+
self::assertSame($expectedPathInfo, $request->getPathInfo());
1895+
}
1896+
1897+
public static function baseUriDetectionOnIisWithRewriteData(): \Generator
1898+
{
1899+
yield 'No rewrite' => [
1900+
[
1901+
'PATH_INFO' => '/foo/bar',
1902+
'PHP_SELF' => '/routingtest/index.php/foo/bar',
1903+
'REQUEST_URI' => '/routingtest/index.php/foo/bar',
1904+
'SCRIPT_FILENAME' => 'C:/Users/derrabus/Projects/routing-test/public/index.php',
1905+
'SCRIPT_NAME' => '/routingtest/index.php',
1906+
],
1907+
'/routingtest/index.php',
1908+
'/foo/bar',
1909+
];
1910+
1911+
yield 'Rewrite with correct case' => [
1912+
[
1913+
'IIS_WasUrlRewritten' => '1',
1914+
'PATH_INFO' => '/foo/bar',
1915+
'PHP_SELF' => '/routingtest/index.php/foo/bar',
1916+
'REQUEST_URI' => '/routingtest/foo/bar',
1917+
'SCRIPT_FILENAME' => 'C:/Users/derrabus/Projects/routing-test/public/index.php',
1918+
'SCRIPT_NAME' => '/routingtest/index.php',
1919+
'UNENCODED_URL' => '/routingtest/foo/bar',
1920+
],
1921+
'/routingtest',
1922+
'/foo/bar',
1923+
];
1924+
1925+
// ISS with UrlRewriteModule might report SCRIPT_NAME/PHP_SELF with wrong case
1926+
// see https://github.com/php/php-src/issues/11981
1927+
yield 'Rewrite with case mismatch' => [
1928+
[
1929+
'IIS_WasUrlRewritten' => '1',
1930+
'PATH_INFO' => '/foo/bar',
1931+
'PHP_SELF' => '/routingtest/index.php/foo/bar',
1932+
'REQUEST_URI' => '/RoutingTest/foo/bar',
1933+
'SCRIPT_FILENAME' => 'C:/Users/derrabus/Projects/routing-test/public/index.php',
1934+
'SCRIPT_NAME' => '/routingtest/index.php',
1935+
'UNENCODED_URL' => '/RoutingTest/foo/bar',
1936+
],
1937+
'/RoutingTest',
1938+
'/foo/bar',
1939+
];
1940+
}
1941+
18861942
/**
18871943
* @dataProvider urlencodedStringPrefixData
18881944
*/

0 commit comments

Comments
 (0)