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