RequestInterface: add hasBody()
hasBody() provides an easy way to check whether the request contains payload data. This ensures this check is performed consistently and in accordance with RFC 9110. Change-Id: If15f2cb6239c4c8170e70a5bec8a5f0821361275
This commit is contained in:
parent
026d8d02a2
commit
36062df690
5 changed files with 128 additions and 0 deletions
|
|
@ -128,4 +128,34 @@ abstract class RequestBase implements RequestInterface {
|
|||
}
|
||||
return $ct;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the client provided a content-length header or a
|
||||
* transfer-encoding header.
|
||||
*
|
||||
* @see https://www.rfc-editor.org/rfc/rfc9110.html#name-content-length
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function hasBody(): bool {
|
||||
// From RFC9110, section 8.6: A user agent SHOULD send Content-Length
|
||||
// in a request when the method defines a meaning for enclosed content
|
||||
// and it is not sending Transfer-Encoding. [...]
|
||||
// A user agent SHOULD NOT send a Content-Length header field when the
|
||||
// request message does not contain content and the method semantics do
|
||||
// not anticipate such data.
|
||||
|
||||
if ( $this->getHeaderLine( 'content-length' ) !== '' ) {
|
||||
// If a content length is set, there is a body
|
||||
return true;
|
||||
}
|
||||
|
||||
if ( $this->getHeaderLine( 'transfer-encoding' ) !== '' ) {
|
||||
// If a transfer encoding is set, there is a body
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -102,4 +102,21 @@ class RequestData extends RequestBase {
|
|||
public function getPostParams() {
|
||||
return $this->postParams;
|
||||
}
|
||||
|
||||
public function hasBody(): bool {
|
||||
if ( parent::hasBody() ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if ( $this->parsedBody !== null ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if ( $this->getBody()->getContents() !== '' ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -268,4 +268,12 @@ interface RequestInterface {
|
|||
public function setParsedBody( ?array $data );
|
||||
|
||||
public function getBodyType(): ?string;
|
||||
|
||||
/**
|
||||
* Determines whether the request has body data associated with it.
|
||||
* Note that this method may return true even if the body is empty.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function hasBody(): bool;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -64,4 +64,34 @@ class RequestBaseTest extends \MediaWikiUnitTestCase {
|
|||
$rb->setHeaders( [ 'Content-type' => 'application/json' ] );
|
||||
$this->assertSame( [ 'application/json' ], $rb->getHeaders()[ 'Content-type' ] );
|
||||
}
|
||||
|
||||
public static function provideHasBody() {
|
||||
yield 'nothing'
|
||||
=> [ [], false ];
|
||||
|
||||
yield 'content-length: 1'
|
||||
=> [ [ 'content-length' => '1' ], true ];
|
||||
|
||||
yield 'content-length: 0'
|
||||
=> [ [ 'content-length' => '0' ], true ];
|
||||
|
||||
yield 'content-length empty'
|
||||
=> [ [ 'content-length' => '' ], false ];
|
||||
|
||||
yield 'transfer-encoding: chunked'
|
||||
=> [ [ 'transfer-encoding' => 'chunked' ], true ];
|
||||
|
||||
yield 'transfer-encoding empty'
|
||||
=> [ [ 'transfer-encoding' => '' ], false ];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider provideHasBody
|
||||
*/
|
||||
public function testHasBody( $headers, $expected ) {
|
||||
$rb = $this->getMockForAbstractClass( RequestBase::class, [ 'cookiePrefix' ] );
|
||||
$rb->setHeaders( $headers );
|
||||
$this->assertSame( $expected, $rb->hasBody() );
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -221,4 +221,47 @@ class RequestDataTest extends \MediaWikiUnitTestCase {
|
|||
$this->assertSame( $expectedResult, $request->getBodyType() );
|
||||
}
|
||||
|
||||
public static function provideHasBody() {
|
||||
yield 'nothing'
|
||||
=> [ [], false ];
|
||||
|
||||
yield 'content-length: 1'
|
||||
=> [ [ 'content-length' => '1' ], true ];
|
||||
|
||||
yield 'content-length: 0'
|
||||
=> [ [ 'content-length' => '0' ], true ];
|
||||
|
||||
yield 'content-length empty'
|
||||
=> [ [ 'content-length' => '' ], false ];
|
||||
|
||||
yield 'transfer-encoding: chunked'
|
||||
=> [ [ 'transfer-encoding' => 'chunked' ], true ];
|
||||
|
||||
yield 'transfer-encoding empty'
|
||||
=> [ [ 'transfer-encoding' => '' ], false ];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider provideHasBody
|
||||
*/
|
||||
public function testHasBodyBasedOnHeader( $headers, $expected ) {
|
||||
$request = new RequestData( [
|
||||
'headers' => $headers
|
||||
] );
|
||||
$this->assertSame( $expected, $request->hasBody() );
|
||||
}
|
||||
|
||||
public function testHasBodyWithContent() {
|
||||
$request = new RequestData( [
|
||||
'bodyContents' => 'test test test'
|
||||
] );
|
||||
$this->assertTrue( $request->hasBody() );
|
||||
}
|
||||
|
||||
public function testHasBodyWithParsedBody() {
|
||||
$request = new RequestData( [
|
||||
'parsedBody' => [ 'foo' => 'bar' ]
|
||||
] );
|
||||
$this->assertTrue( $request->hasBody() );
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue