apache_request_headers() is a vendor-specific function - it got used
when present and alternative code paths were exercised otherwise.
These preserved certain "special" headers, e.g. Content-Type, only
inconsistently.
The function getallheaders() is an alias[1] for apache_request_headers()
on systems where the latter is present. Alternatively, there is a
polyfill (ralouphie/getallheaders) which is already installed in
mediawiki-vendor[2] (by virtue of guzzle).
Using getallheaders() exclusively, will make sure these "special"
headers are consistently available alongside their "regular"[3] peers
and helps MediaWiki code focus on its domain.
The dependency to ralouphie/getallheaders is made explicit in the same
version in which it is currently locked in mediawiki-vendor[4].
This surfaced because the deprecation warning for API POST requests
without a Content-Type header, introduced in bba1a0f, appeared in my
development system (somewhat dated addshore/mediawiki-docker-dev/) even
though the client did a fine job.
Interesting implementation detail: While WebRequest keeps track of
headers using keys in all upper case, REST RequestFromGlobals does so in
all lower case - but both use retrieval logic complementary to their
respective approach however. In case of REST RequestFromGlobals this is
encapsulated inside of HeaderContainer (setting and retrieving), while
WebRequest does all of this by itself. Cf. [5] and [6]
[1]: https://www.php.net/manual/en/function.getallheaders.php
[2]: https://github.com/wikimedia/mediawiki-vendor/tree/8f2967d/ralouphie/getallheaders
[3]: https://www.php.net/manual/en/reserved.variables.server.php#110763
[4]: https://github.com/wikimedia/mediawiki-vendor/blob/8f2967d/composer.lock#L3250
[5]: https://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.2
[6]: https://www.php.net/manual/en/function.apache-request-headers.php#124236
Bug: T245535
Change-Id: Iba52f152e15928473b729a2588c2462e76e85634
191 lines
4.3 KiB
PHP
191 lines
4.3 KiB
PHP
<?php
|
|
|
|
use GuzzleHttp\Psr7\UploadedFile;
|
|
use MediaWiki\Rest\RequestFromGlobals;
|
|
|
|
// phpcs:disable MediaWiki.Usage.SuperGlobalsUsage.SuperGlobals
|
|
|
|
/**
|
|
* @covers \MediaWiki\Rest\RequestFromGlobals
|
|
*/
|
|
class RequestFromGlobalsTest extends MediaWikiTestCase {
|
|
/**
|
|
* @var RequestFromGlobals
|
|
*/
|
|
private $reqFromGlobals;
|
|
|
|
protected function setUp() : void {
|
|
parent::setUp();
|
|
$this->reqFromGlobals = new RequestFromGlobals();
|
|
}
|
|
|
|
/**
|
|
* @dataProvider provideGetMethod
|
|
*/
|
|
public function testGetMethod( $serverVars, $expected ) {
|
|
$this->setServerVars( $serverVars );
|
|
$this->assertEquals( $this->reqFromGlobals->getMethod(), $expected );
|
|
}
|
|
|
|
public static function provideGetMethod() {
|
|
return [
|
|
[
|
|
[
|
|
'REQUEST_METHOD' => 'POST'
|
|
],
|
|
'POST',
|
|
],
|
|
[
|
|
[],
|
|
'GET',
|
|
]
|
|
];
|
|
}
|
|
|
|
public function testGetUri() {
|
|
$this->setServerVars( [
|
|
'REQUEST_URI' => '/test.php'
|
|
] );
|
|
|
|
$this->assertEquals( $this->reqFromGlobals->getUri(), '/test.php' );
|
|
}
|
|
|
|
/**
|
|
* @dataProvider provideGetProtocolVersion
|
|
*/
|
|
public function testGetProtocolVersion( $serverVars, $expected ) {
|
|
$this->setServerVars( $serverVars );
|
|
$this->assertEquals( $this->reqFromGlobals->getProtocolVersion(), $expected );
|
|
}
|
|
|
|
public static function provideGetProtocolVersion() {
|
|
return [
|
|
[
|
|
[
|
|
'SERVER_PROTOCOL' => 'HTTP/2'
|
|
],
|
|
2
|
|
],
|
|
[
|
|
[],
|
|
1.1
|
|
]
|
|
];
|
|
}
|
|
|
|
public function testGetHeaders() {
|
|
$this->setServerVars( [
|
|
'HTTP_HOST' => '[::1]',
|
|
'CONTENT_LENGTH' => 6,
|
|
'CONTENT_TYPE' => 'application/json',
|
|
'CONTENT_MD5' => 'rL0Y20zC+Fzt72VPzMSk2A==',
|
|
] );
|
|
|
|
$this->assertEquals( $this->reqFromGlobals->getHeaders(), [
|
|
'Host' => [ '[::1]' ],
|
|
'Content-Length' => [ 6 ],
|
|
'Content-Type' => [ 'application/json' ],
|
|
'Content-Md5' => [ 'rL0Y20zC+Fzt72VPzMSk2A==' ],
|
|
] );
|
|
}
|
|
|
|
public function testGetHeaderKeyIsCaseInsensitive() {
|
|
$cacheControl = 'private, must-revalidate, max-age=0';
|
|
$this->setServerVars( [ 'HTTP_CACHE_CONTROL' => $cacheControl ] );
|
|
|
|
$this->assertSame( $this->reqFromGlobals->getHeader( 'Cache-Control' ), [ $cacheControl ] );
|
|
$this->assertSame( $this->reqFromGlobals->getHeader( 'cache-control' ), [ $cacheControl ] );
|
|
}
|
|
|
|
public function testGetBody() {
|
|
$this->setServerVars( [
|
|
'REQUEST_METHOD' => 'POST',
|
|
'HTTP_ACCEPT' => 'text/html'
|
|
] );
|
|
|
|
$this->assertEquals( $this->reqFromGlobals->getBody(), '' );
|
|
}
|
|
|
|
public function testGetServerParams() {
|
|
$serverVars = [
|
|
'SERVER_NAME' => 'www.mediawiki.org',
|
|
'SERVER_PROTOCOL' => 'HTTP/1.1',
|
|
'REQUEST_METHOD' => 'POST',
|
|
'HTTP_HOST' => 'www.mediawiki.org',
|
|
'HTTP_ACCEPT' => 'text/html',
|
|
'REMOTE_PORT' => '1234',
|
|
'SCRIPT_NAME' => '/index.php',
|
|
];
|
|
$this->setServerVars( $serverVars );
|
|
|
|
$expectedServerParams = $this->reqFromGlobals->getServerParams();
|
|
|
|
$diffs = array_diff_assoc( $expectedServerParams, $serverVars );
|
|
|
|
$this->assertEquals( count( $diffs ), 2 );
|
|
$this->assertArrayHasKey( 'REQUEST_TIME_FLOAT', $diffs );
|
|
$this->assertArrayHasKey( 'REQUEST_TIME', $diffs );
|
|
}
|
|
|
|
public function testGetCookieParams() {
|
|
$_COOKIE = [
|
|
'testcookie' => true
|
|
];
|
|
|
|
$this->assertEquals( $this->reqFromGlobals->getCookieParams(), [ 'testcookie' => true ] );
|
|
}
|
|
|
|
public function testGetQueryParams() {
|
|
$query = [
|
|
[
|
|
'title' => 'foo',
|
|
'action' => 'query'
|
|
]
|
|
];
|
|
$_GET = $query;
|
|
|
|
$this->assertEquals( $this->reqFromGlobals->getQueryParams(), $query );
|
|
}
|
|
|
|
public function testGetUploadedFiles() {
|
|
$_FILES = [
|
|
'file' => [
|
|
'name' => 'Foo.txt',
|
|
'type' => 'text/plain',
|
|
'tmp_name' => '/tmp/foobar',
|
|
'error' => UPLOAD_ERR_OK,
|
|
'size' => 20,
|
|
]
|
|
];
|
|
|
|
$this->assertEquals( $this->reqFromGlobals->getUploadedFiles(), [
|
|
'file' => new UploadedFile(
|
|
'/tmp/foobar',
|
|
20, UPLOAD_ERR_OK,
|
|
'Foo.txt',
|
|
'text/plain'
|
|
)
|
|
] );
|
|
}
|
|
|
|
public function testGetPostParams() {
|
|
$form = [
|
|
'token' => '983yh4edji',
|
|
'action' => 'login'
|
|
];
|
|
$_POST = $form;
|
|
|
|
$this->assertEquals( $this->reqFromGlobals->getPostParams(), $form );
|
|
}
|
|
|
|
protected function setServerVars( $vars ) {
|
|
// Don't remove vars which should be available in all SAPI.
|
|
if ( !isset( $vars['REQUEST_TIME_FLOAT'] ) ) {
|
|
$vars['REQUEST_TIME_FLOAT'] = $_SERVER['REQUEST_TIME_FLOAT'];
|
|
}
|
|
if ( !isset( $vars['REQUEST_TIME'] ) ) {
|
|
$vars['REQUEST_TIME'] = $_SERVER['REQUEST_TIME'];
|
|
}
|
|
$_SERVER = $vars;
|
|
}
|
|
}
|