Rest: Handle Uri constructor exception

All titles that contain a colon followed by a number cannot, currently,
be accessed via the Rest endpoint.

For example https://en.wikipedia.org/wiki/3:33 is a valid title/article
on English Wikipedia and can be accessed there the index/api.php entry
points. But the rest endpoint will fatal:
https://en.wikipedia.org/w/rest.php/v1/page/3:33/history

The exception is thrown in Uri constructor of GuzzleHttp library
if parse_url() failed to parse the request URL. But parse_url() has
an open bug of failing to parse URLs that contain the above pattern.
The function returns false in such cases, (it previously raised warning
see I2715607);

To make our titles with this pattern accessible, we have to forestall
this exception.

Bug: T256831
Change-Id: Ib829afc7b33419b01e69ababa147d33b30c0fbcb
This commit is contained in:
Ammar Abdulhamid 2020-07-01 12:22:33 +01:00 committed by Ammarpad
parent a061a61bb8
commit 4079d328e7
2 changed files with 34 additions and 1 deletions

View file

@ -33,7 +33,31 @@ class RequestFromGlobals extends RequestBase {
public function getUri() {
if ( $this->uri === null ) {
$this->uri = new Uri( \WebRequest::getGlobalRequestURL() );
$requestUrl = \WebRequest::getGlobalRequestURL();
// Uri constructor will throw exception if parse_url() fails to parse
// the $requestUrl. This will happen if the URL is relative and contains
// colon-number pattern that looks like a port.
//
// Since $requestUrl here is absolute-path references so all titles that
// contain colon followed by a number would be inacessible if the exception
// occurs. To forestall the exception we temporarily turn the request URL
// into to absolute form before instantiating the Uri and we turn it back to
// its absolute-path reference form afterwards. T256831.
$needsAbsoluteUrl = parse_url( $requestUrl ) === false;
if ( $needsAbsoluteUrl ) {
$requestUrl = \WebRequest::detectProtocol() === 'http'
? wfGetServerUrl( PROTO_HTTP ) . $requestUrl
: wfGetServerUrl( PROTO_HTTPS ) . $requestUrl;
// Instantiates Uri and remove the temporary host and scheme that
// we added to turn the URL back to its absolute-path reference form.
$uriInstance = new Uri( $requestUrl );
$this->uri = $uriInstance->withScheme( '' )->withHost( '' );
} else {
$this->uri = new Uri( $requestUrl );
}
}
return $this->uri;
}

View file

@ -50,6 +50,15 @@ class RequestFromGlobalsTest extends MediaWikiIntegrationTestCase {
$this->assertEquals( $this->reqFromGlobals->getUri(), '/test.php' );
}
public function testGetUri2() {
$this->setServerVars( [
'REQUEST_URI' => '/test.php/page/1:1',
'SERVER_PORT' => 9412
] );
$this->assertEquals( $this->reqFromGlobals->getUri(), '//:9412/test.php/page/1:1' );
}
/**
* @dataProvider provideGetProtocolVersion
*/