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