1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161
|
<?php
namespace MediaWiki\Rest;
/**
* Shared code between RequestData and RequestFromGlobals
*/
abstract class RequestBase implements RequestInterface {
/**
* @var HeaderContainer|null
*/
private $headerCollection;
/** @var array */
private $pathParams = [];
/** @var string */
private $cookiePrefix;
protected ?array $parsedBody = null;
/**
* @internal
* @param string $cookiePrefix
*/
public function __construct( $cookiePrefix ) {
$this->cookiePrefix = $cookiePrefix;
}
/**
* Override this in the implementation class if lazy initialisation of
* header values is desired. It should call setHeaders().
*
* @internal
*/
protected function initHeaders() {
}
public function __clone() {
if ( $this->headerCollection !== null ) {
$this->headerCollection = clone $this->headerCollection;
}
}
/**
* Erase any existing headers and replace them with the specified header
* lines.
*
* Call this either from the constructor or from initHeaders() of the
* implementing class.
*
* @internal
* @param string[] $headers The header lines
*/
public function setHeaders( $headers ) {
$this->headerCollection = new HeaderContainer;
$this->headerCollection->resetHeaders( $headers );
}
public function getHeaders() {
if ( $this->headerCollection === null ) {
$this->initHeaders();
}
return $this->headerCollection->getHeaders();
}
public function getHeader( $name ) {
if ( $this->headerCollection === null ) {
$this->initHeaders();
}
return $this->headerCollection->getHeader( $name );
}
public function hasHeader( $name ) {
if ( $this->headerCollection === null ) {
$this->initHeaders();
}
return $this->headerCollection->hasHeader( $name );
}
public function getHeaderLine( $name ) {
if ( $this->headerCollection === null ) {
$this->initHeaders();
}
return $this->headerCollection->getHeaderLine( $name );
}
public function setPathParams( $params ) {
$this->pathParams = $params;
}
public function getPathParams() {
return $this->pathParams;
}
public function getPathParam( $name ) {
return $this->pathParams[$name] ?? null;
}
public function getCookiePrefix() {
return $this->cookiePrefix;
}
public function getCookie( $name, $default = null ) {
$cookies = $this->getCookieParams();
$prefixedName = $this->getCookiePrefix() . $name;
if ( array_key_exists( $prefixedName, $cookies ) ) {
return $cookies[$prefixedName];
} else {
return $default;
}
}
public function getParsedBody(): ?array {
return $this->parsedBody;
}
public function setParsedBody( ?array $data ) {
$this->parsedBody = $data;
}
public function getBodyType(): ?string {
[ $ct ] = explode( ';', $this->getHeaderLine( 'Content-Type' ), 2 );
$ct = strtolower( trim( $ct ) );
if ( $ct === '' ) {
return null;
}
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;
}
}
|