Request.php 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266
  1. <?php
  2. declare(strict_types=1);
  3. namespace Sabre\HTTP;
  4. use Sabre\Uri;
  5. /**
  6. * The Request class represents a single HTTP request.
  7. *
  8. * You can either simply construct the object from scratch, or if you need
  9. * access to the current HTTP request, use Sapi::getRequest.
  10. *
  11. * @copyright Copyright (C) fruux GmbH (https://fruux.com/)
  12. * @author Evert Pot (http://evertpot.com/)
  13. * @license http://sabre.io/license/ Modified BSD License
  14. */
  15. class Request extends Message implements RequestInterface
  16. {
  17. /**
  18. * HTTP Method.
  19. *
  20. * @var string
  21. */
  22. protected $method;
  23. /**
  24. * Request Url.
  25. *
  26. * @var string
  27. */
  28. protected $url;
  29. /**
  30. * Creates the request object.
  31. *
  32. * @param resource|callable|string $body
  33. */
  34. public function __construct(string $method, string $url, array $headers = [], $body = null)
  35. {
  36. $this->setMethod($method);
  37. $this->setUrl($url);
  38. $this->setHeaders($headers);
  39. $this->setBody($body);
  40. }
  41. /**
  42. * Returns the current HTTP method.
  43. */
  44. public function getMethod(): string
  45. {
  46. return $this->method;
  47. }
  48. /**
  49. * Sets the HTTP method.
  50. */
  51. public function setMethod(string $method)
  52. {
  53. $this->method = $method;
  54. }
  55. /**
  56. * Returns the request url.
  57. */
  58. public function getUrl(): string
  59. {
  60. return $this->url;
  61. }
  62. /**
  63. * Sets the request url.
  64. */
  65. public function setUrl(string $url)
  66. {
  67. $this->url = $url;
  68. }
  69. /**
  70. * Returns the list of query parameters.
  71. *
  72. * This is equivalent to PHP's $_GET superglobal.
  73. */
  74. public function getQueryParameters(): array
  75. {
  76. $url = $this->getUrl();
  77. if (false === ($index = strpos($url, '?'))) {
  78. return [];
  79. }
  80. parse_str(substr($url, $index + 1), $queryParams);
  81. return $queryParams;
  82. }
  83. protected $absoluteUrl;
  84. /**
  85. * Sets the absolute url.
  86. */
  87. public function setAbsoluteUrl(string $url)
  88. {
  89. $this->absoluteUrl = $url;
  90. }
  91. /**
  92. * Returns the absolute url.
  93. */
  94. public function getAbsoluteUrl(): string
  95. {
  96. if (!$this->absoluteUrl) {
  97. // Guessing we're a http endpoint.
  98. $this->absoluteUrl = 'http://'.
  99. ($this->getHeader('Host') ?? 'localhost').
  100. $this->getUrl();
  101. }
  102. return $this->absoluteUrl;
  103. }
  104. /**
  105. * Base url.
  106. *
  107. * @var string
  108. */
  109. protected $baseUrl = '/';
  110. /**
  111. * Sets a base url.
  112. *
  113. * This url is used for relative path calculations.
  114. */
  115. public function setBaseUrl(string $url)
  116. {
  117. $this->baseUrl = $url;
  118. }
  119. /**
  120. * Returns the current base url.
  121. */
  122. public function getBaseUrl(): string
  123. {
  124. return $this->baseUrl;
  125. }
  126. /**
  127. * Returns the relative path.
  128. *
  129. * This is being calculated using the base url. This path will not start
  130. * with a slash, so it will always return something like
  131. * 'example/path.html'.
  132. *
  133. * If the full path is equal to the base url, this method will return an
  134. * empty string.
  135. *
  136. * This method will also urldecode the path, and if the url was encoded as
  137. * ISO-8859-1, it will convert it to UTF-8.
  138. *
  139. * If the path is outside of the base url, a LogicException will be thrown.
  140. */
  141. public function getPath(): string
  142. {
  143. // Removing duplicated slashes.
  144. $uri = str_replace('//', '/', $this->getUrl());
  145. $uri = Uri\normalize($uri);
  146. $baseUri = Uri\normalize($this->getBaseUrl());
  147. if (0 === strpos($uri, $baseUri)) {
  148. // We're not interested in the query part (everything after the ?).
  149. list($uri) = explode('?', $uri);
  150. return trim(decodePath(substr($uri, strlen($baseUri))), '/');
  151. }
  152. if ($uri.'/' === $baseUri) {
  153. return '';
  154. }
  155. // A special case, if the baseUri was accessed without a trailing
  156. // slash, we'll accept it as well.
  157. throw new \LogicException('Requested uri ('.$this->getUrl().') is out of base uri ('.$this->getBaseUrl().')');
  158. }
  159. /**
  160. * Equivalent of PHP's $_POST.
  161. *
  162. * @var array
  163. */
  164. protected $postData = [];
  165. /**
  166. * Sets the post data.
  167. *
  168. * This is equivalent to PHP's $_POST superglobal.
  169. *
  170. * This would not have been needed, if POST data was accessible as
  171. * php://input, but unfortunately we need to special case it.
  172. */
  173. public function setPostData(array $postData)
  174. {
  175. $this->postData = $postData;
  176. }
  177. /**
  178. * Returns the POST data.
  179. *
  180. * This is equivalent to PHP's $_POST superglobal.
  181. */
  182. public function getPostData(): array
  183. {
  184. return $this->postData;
  185. }
  186. /**
  187. * An array containing the raw _SERVER array.
  188. *
  189. * @var array
  190. */
  191. protected $rawServerData;
  192. /**
  193. * Returns an item from the _SERVER array.
  194. *
  195. * If the value does not exist in the array, null is returned.
  196. *
  197. * @return string|null
  198. */
  199. public function getRawServerValue(string $valueName)
  200. {
  201. return $this->rawServerData[$valueName] ?? null;
  202. }
  203. /**
  204. * Sets the _SERVER array.
  205. */
  206. public function setRawServerData(array $data)
  207. {
  208. $this->rawServerData = $data;
  209. }
  210. /**
  211. * Serializes the request object as a string.
  212. *
  213. * This is useful for debugging purposes.
  214. */
  215. public function __toString(): string
  216. {
  217. $out = $this->getMethod().' '.$this->getUrl().' HTTP/'.$this->getHttpVersion()."\r\n";
  218. foreach ($this->getHeaders() as $key => $value) {
  219. foreach ($value as $v) {
  220. if ('Authorization' === $key) {
  221. list($v) = explode(' ', $v, 2);
  222. $v .= ' REDACTED';
  223. }
  224. $out .= $key.': '.$v."\r\n";
  225. }
  226. }
  227. $out .= "\r\n";
  228. $out .= $this->getBodyAsString();
  229. return $out;
  230. }
  231. }