You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
202 lines
6.0 KiB
202 lines
6.0 KiB
<?php |
|
|
|
namespace Sabre\HTTP; |
|
|
|
/** |
|
* PHP SAPI |
|
* |
|
* This object is responsible for: |
|
* 1. Constructing a Request object based on the current HTTP request sent to |
|
* the PHP process. |
|
* 2. Sending the Response object back to the client. |
|
* |
|
* It could be said that this class provides a mapping between the Request and |
|
* Response objects, and php's: |
|
* |
|
* * $_SERVER |
|
* * $_POST |
|
* * $_FILES |
|
* * php://input |
|
* * echo() |
|
* * header() |
|
* * php://output |
|
* |
|
* You can choose to either call all these methods statically, but you can also |
|
* instantiate this as an object to allow for polymorhpism. |
|
* |
|
* @copyright Copyright (C) fruux GmbH (https://fruux.com/) |
|
* @author Evert Pot (http://evertpot.com/) |
|
* @license http://sabre.io/license/ Modified BSD License |
|
*/ |
|
class Sapi { |
|
|
|
/** |
|
* This static method will create a new Request object, based on the |
|
* current PHP request. |
|
* |
|
* @return Request |
|
*/ |
|
static function getRequest() { |
|
|
|
$r = self::createFromServerArray($_SERVER); |
|
$r->setBody(fopen('php://input', 'r')); |
|
$r->setPostData($_POST); |
|
return $r; |
|
|
|
} |
|
|
|
/** |
|
* Sends the HTTP response back to a HTTP client. |
|
* |
|
* This calls php's header() function and streams the body to php://output. |
|
* |
|
* @param ResponseInterface $response |
|
* @return void |
|
*/ |
|
static function sendResponse(ResponseInterface $response) { |
|
|
|
header('HTTP/' . $response->getHttpVersion() . ' ' . $response->getStatus() . ' ' . $response->getStatusText()); |
|
foreach ($response->getHeaders() as $key => $value) { |
|
|
|
foreach ($value as $k => $v) { |
|
if ($k === 0) { |
|
header($key . ': ' . $v); |
|
} else { |
|
header($key . ': ' . $v, false); |
|
} |
|
} |
|
|
|
} |
|
|
|
$body = $response->getBody(); |
|
if (is_null($body)) return; |
|
|
|
$contentLength = $response->getHeader('Content-Length'); |
|
if ($contentLength !== null) { |
|
$output = fopen('php://output', 'wb'); |
|
if (is_resource($body) && get_resource_type($body) == 'stream') { |
|
if (PHP_INT_SIZE !== 4){ |
|
// use the dedicated function on 64 Bit systems |
|
stream_copy_to_stream($body, $output, $contentLength); |
|
} else { |
|
// workaround for 32 Bit systems to avoid stream_copy_to_stream |
|
while (!feof($body)) { |
|
fwrite($output, fread($body, 8192)); |
|
} |
|
} |
|
} else { |
|
fwrite($output, $body, $contentLength); |
|
} |
|
} else { |
|
file_put_contents('php://output', $body); |
|
} |
|
|
|
if (is_resource($body)) { |
|
fclose($body); |
|
} |
|
|
|
} |
|
|
|
/** |
|
* This static method will create a new Request object, based on a PHP |
|
* $_SERVER array. |
|
* |
|
* @param array $serverArray |
|
* @return Request |
|
*/ |
|
static function createFromServerArray(array $serverArray) { |
|
|
|
$headers = []; |
|
$method = null; |
|
$url = null; |
|
$httpVersion = '1.1'; |
|
|
|
$protocol = 'http'; |
|
$hostName = 'localhost'; |
|
|
|
foreach ($serverArray as $key => $value) { |
|
|
|
switch ($key) { |
|
|
|
case 'SERVER_PROTOCOL' : |
|
if ($value === 'HTTP/1.0') { |
|
$httpVersion = '1.0'; |
|
} |
|
break; |
|
case 'REQUEST_METHOD' : |
|
$method = $value; |
|
break; |
|
case 'REQUEST_URI' : |
|
$url = $value; |
|
break; |
|
|
|
// These sometimes show up without a HTTP_ prefix |
|
case 'CONTENT_TYPE' : |
|
$headers['Content-Type'] = $value; |
|
break; |
|
case 'CONTENT_LENGTH' : |
|
$headers['Content-Length'] = $value; |
|
break; |
|
|
|
// mod_php on apache will put credentials in these variables. |
|
// (fast)cgi does not usually do this, however. |
|
case 'PHP_AUTH_USER' : |
|
if (isset($serverArray['PHP_AUTH_PW'])) { |
|
$headers['Authorization'] = 'Basic ' . base64_encode($value . ':' . $serverArray['PHP_AUTH_PW']); |
|
} |
|
break; |
|
|
|
// Similarly, mod_php may also screw around with digest auth. |
|
case 'PHP_AUTH_DIGEST' : |
|
$headers['Authorization'] = 'Digest ' . $value; |
|
break; |
|
|
|
// Apache may prefix the HTTP_AUTHORIZATION header with |
|
// REDIRECT_, if mod_rewrite was used. |
|
case 'REDIRECT_HTTP_AUTHORIZATION' : |
|
$headers['Authorization'] = $value; |
|
break; |
|
|
|
case 'HTTP_HOST' : |
|
$hostName = $value; |
|
$headers['Host'] = $value; |
|
break; |
|
|
|
case 'HTTPS' : |
|
if (!empty($value) && $value !== 'off') { |
|
$protocol = 'https'; |
|
} |
|
break; |
|
|
|
default : |
|
if (substr($key, 0, 5) === 'HTTP_') { |
|
// It's a HTTP header |
|
|
|
// Normalizing it to be prettier |
|
$header = strtolower(substr($key, 5)); |
|
|
|
// Transforming dashes into spaces, and uppercasing |
|
// every first letter. |
|
$header = ucwords(str_replace('_', ' ', $header)); |
|
|
|
// Turning spaces into dashes. |
|
$header = str_replace(' ', '-', $header); |
|
$headers[$header] = $value; |
|
|
|
} |
|
break; |
|
|
|
|
|
} |
|
|
|
} |
|
|
|
$r = new Request($method, $url, $headers); |
|
$r->setHttpVersion($httpVersion); |
|
$r->setRawServerData($serverArray); |
|
$r->setAbsoluteUrl($protocol . '://' . $hostName . $url); |
|
return $r; |
|
|
|
} |
|
|
|
}
|
|
|