mirror of
https://github.com/OpenXE-org/OpenXE.git
synced 2024-11-16 13:07:14 +01:00
433 lines
12 KiB
PHP
433 lines
12 KiB
PHP
<?php
|
|
|
|
namespace Xentral\Modules\Api\Http;
|
|
|
|
use Xentral\Modules\Api\Http\Exception\MethodNotAllowedException;
|
|
|
|
/**
|
|
* @deprecated Use Xentral\Components\Http instead
|
|
*/
|
|
class Request
|
|
{
|
|
/** @var array $supportedMethods */
|
|
protected static $supportedMethods = [
|
|
'GET', 'POST', 'PUT', 'DELETE',
|
|
];
|
|
|
|
/** @var array $attributes */
|
|
public $attributes;
|
|
|
|
/** @var array $query $_GET-Parameter */
|
|
public $query;
|
|
|
|
/** @var array $request $_POST-Parameter */
|
|
public $request;
|
|
|
|
/** @var array $server $_SERVER-Parameter */
|
|
public $server;
|
|
|
|
/** @var array $headers */
|
|
public $headers;
|
|
|
|
/** @var string $method */
|
|
protected $method;
|
|
|
|
/** @var string $pathInfo */
|
|
protected $pathInfo;
|
|
|
|
/** @var string $requestUri */
|
|
protected $requestUri;
|
|
|
|
/** @var string $content */
|
|
protected $content;
|
|
|
|
/** @var array $acceptableContentTypes */
|
|
protected $acceptableContentTypes;
|
|
|
|
/**
|
|
* @param array $query
|
|
* @param array $request
|
|
* @param array $server
|
|
* @param array $files
|
|
* @param array $cookies
|
|
* @param string $content
|
|
*/
|
|
public function __construct(
|
|
array $query = [],
|
|
array $request = [],
|
|
array $server = [],
|
|
array $files = [],
|
|
array $cookies = [],
|
|
$content = null
|
|
) {
|
|
$this->query = new ParameterCollection(!empty($query) ? $query : $_GET);
|
|
$this->request = new ParameterCollection(!empty($request) ? $request : $_POST);
|
|
$this->server = new ServerParameter(!empty($server) ? $server : $_SERVER);
|
|
// $this->files = $_FILES; // @todo
|
|
// $this->cookies = $_COOKIE; // @todo
|
|
$this->attributes = new ParameterCollection([]);
|
|
$this->headers = new ParameterCollection($this->server->getHeaders());
|
|
|
|
$this->method = $this->getMethod();
|
|
$this->requestUri = $this->getRequestUri();
|
|
$this->pathInfo = $this->getPathInfo();
|
|
$this->content = $content;
|
|
}
|
|
|
|
/**
|
|
* @return Request
|
|
*/
|
|
public static function createFromGlobals()
|
|
{
|
|
return new static($_GET, $_POST, $_SERVER, [], []);
|
|
}
|
|
|
|
/**
|
|
* @deprecated Use Xentral\Tests\Http\RequestFactory instead
|
|
*
|
|
* @param string $uri
|
|
* @param string $method
|
|
* @param array $params $_GET oder $_POST-Parameter
|
|
* @param array $server
|
|
* @param string $content
|
|
*
|
|
* @return Request
|
|
*/
|
|
public static function create($uri, $method = 'GET', $params = [], $server = [], $content = null)
|
|
{
|
|
// Default-Settings
|
|
$serverDefault = [
|
|
'HTTP_HOST' => 'localhost',
|
|
'HTTP_ACCEPT' => 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
|
|
'PATH_INFO' => '',
|
|
'REMOTE_ADDRESS' => '127.0.0.1',
|
|
'REQUEST_METHOD' => 'GET',
|
|
'REQUEST_SCHEME' => 'http',
|
|
'REQUEST_TIME' => time(),
|
|
'SCRIPT_NAME' => '',
|
|
'SCRIPT_FILENAME' => '',
|
|
'SERVER_NAME' => 'localhost',
|
|
'SERVER_PORT' => '80',
|
|
'SERVER_PROTOCOL' => 'HTTP/1.1'
|
|
];
|
|
|
|
$server = array_merge($serverDefault, $server);
|
|
|
|
if ($method !== 'GET' && in_array($method, self::$supportedMethods, true)) {
|
|
$server['REQUEST_METHOD'] = strtoupper($method);
|
|
}
|
|
|
|
$queryParams = [];
|
|
$requestParams = [];
|
|
if ($method === 'GET') {
|
|
$queryParams = $params;
|
|
} elseif (in_array($method, ['POST', 'PUT'])) {
|
|
$requestParams = $params;
|
|
}
|
|
|
|
$uriParts = parse_url($uri);
|
|
|
|
if (!empty($uriParts['scheme'])) {
|
|
$server['REQUEST_SCHEME'] = $uriParts['scheme'];
|
|
}
|
|
|
|
if (!empty($uriParts['host'])) {
|
|
$server['HTTP_HOST'] = $uriParts['host'];
|
|
$server['SERVER_NAME'] = $uriParts['host'];
|
|
}
|
|
|
|
if (!empty($uriParts['port'])) {
|
|
$server['SERVER_PORT'] = (string)$uriParts['port'];
|
|
$server['HTTP_HOST'] .= ':' . $uriParts['port'];
|
|
}
|
|
|
|
if (!isset($uriParts['path'])) {
|
|
$uriParts['path'] = '/';
|
|
}
|
|
|
|
$server['REQUEST_URI'] = $uriParts['path'];
|
|
|
|
$queryString = '';
|
|
if (!empty($uriParts['query'])) {
|
|
$queryString = $uriParts['query'];
|
|
|
|
// @todo URL-Parameter und $queryParams zusammenführen
|
|
|
|
} else {
|
|
if (!empty($queryParams)) {
|
|
$queryString = http_build_query($queryParams, '', '&');
|
|
}
|
|
}
|
|
|
|
$server['QUERY_STRING'] = $queryString;
|
|
if (!empty($queryString)) {
|
|
$server['REQUEST_URI'] .= '?' . $queryString;
|
|
}
|
|
|
|
return new static($queryParams, $requestParams, $server, [], [], $content);
|
|
}
|
|
|
|
/**
|
|
* @param string $name
|
|
* @param string $value
|
|
*/
|
|
public function setHeader($name, $value)
|
|
{
|
|
$this->headers[$name] = $value;
|
|
}
|
|
|
|
/**
|
|
* @param string $name
|
|
*
|
|
* @return string
|
|
*/
|
|
public function getHeader($name)
|
|
{
|
|
return $this->headers[$name];
|
|
}
|
|
|
|
/**
|
|
* @return array
|
|
*/
|
|
public function getHeaders()
|
|
{
|
|
return $this->headers;
|
|
}
|
|
|
|
/**
|
|
* @param string $method
|
|
*/
|
|
public function setMethod($method)
|
|
{
|
|
$this->method = $method;
|
|
}
|
|
|
|
/**
|
|
* @return string
|
|
*/
|
|
public function getMethod()
|
|
{
|
|
if (null === $this->method) {
|
|
$method = strtoupper($this->server->get('REQUEST_METHOD') ?: 'GET');
|
|
if (!in_array($method, self::$supportedMethods, true)) {
|
|
throw new MethodNotAllowedException(self::$supportedMethods);
|
|
}
|
|
$this->method = $method;
|
|
}
|
|
|
|
return $this->method;
|
|
}
|
|
|
|
/**
|
|
* @return string
|
|
*/
|
|
public function getRequestUri()
|
|
{
|
|
if (null === $this->requestUri) {
|
|
$this->requestUri = $this->server->get('REQUEST_URI');
|
|
}
|
|
|
|
return $this->requestUri;
|
|
}
|
|
|
|
/**
|
|
* @return string
|
|
*/
|
|
public function getPathInfo()
|
|
{
|
|
if (null === $this->pathInfo) {
|
|
$this->pathInfo = !empty($this->server->get('PATH_INFO')) ? $this->server->get('PATH_INFO') : '/';
|
|
}
|
|
|
|
return $this->pathInfo;
|
|
}
|
|
|
|
/**
|
|
* @deprecated Use PathInfoDetector instead
|
|
*
|
|
* Gibt den berechneten PathInfo-Teil der URL zurück; ohne $_SERVER['PATH_INFO'] zu verwenden
|
|
*
|
|
* Wird benötigt um Fehler in der Server-Konfiguration zu erkennen
|
|
*
|
|
* @return string|false false wenn PathInfo nicht rekonstruiert werden kann
|
|
*/
|
|
public function getDetectedPathInfo()
|
|
{
|
|
$scriptName = $this->getSafeScriptName();
|
|
if (empty($scriptName)) {
|
|
return false; // Fehlerhafte Webserver-Konfiguration
|
|
}
|
|
|
|
// PathInfo aus $_SERVER['DOCUMENT_URI'] ermitteln
|
|
// Bei Apache nicht gesetzt! Nur bei Nginx und PHP-FPM gesetzt; abhängig von Konfiguration!
|
|
$docUri = $this->server->get('DOCUMENT_URI');
|
|
if (!empty($docUri) && strpos($docUri, $scriptName) === 0) {
|
|
return substr($docUri, strlen($scriptName));
|
|
}
|
|
|
|
// PathInfo aus $_SERVER['PHP_SELF'] ermitteln
|
|
$phpSelf = $this->server->get('PHP_SELF');
|
|
if (strpos($phpSelf, $scriptName) === 0) {
|
|
return substr($phpSelf, strlen($scriptName));
|
|
}
|
|
|
|
// PathInfo aus $_SERVER['REQUEST_URI'] ermitteln; ohne URL-Rewriting
|
|
// Request-URI kann Query-Parameter enthalten!
|
|
$reqUri = $this->server->get('REQUEST_URI');
|
|
if (!empty($reqUri) && strpos($reqUri, $scriptName) === 0) {
|
|
$pathInfoWithQueryParams = substr($reqUri, strlen($scriptName));
|
|
|
|
return $this->trimQueryParams($pathInfoWithQueryParams);
|
|
}
|
|
|
|
// Komplexeres URL-Rewriting, oder fehlerhafte Webserver-Konfiguration
|
|
// => PathInfo kann nicht rekonstruiert werden
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Ermittelt $_SERVER['SCRIPT_NAME'] ohne PathInfo
|
|
*
|
|
* Unter Nginx + PHP-FPM kann(!) der $_SERVER['SCRIPT_NAME'] auch den PathInfo enthalten.
|
|
*
|
|
* @return string
|
|
*/
|
|
private function getSafeScriptName()
|
|
{
|
|
$scriptFilename = $this->server->get('SCRIPT_FILENAME');
|
|
$documentRoot = $this->server->get('DOCUMENT_ROOT');
|
|
|
|
if (strpos($scriptFilename, $documentRoot) === 0) {
|
|
return substr($scriptFilename, strlen($documentRoot));
|
|
}
|
|
|
|
return $this->server->get('SCRIPT_NAME');
|
|
}
|
|
|
|
/**
|
|
* @param bool $withQueryParams GET-Parameter mitliefern?
|
|
*
|
|
* @return string
|
|
*/
|
|
public function getFullUri($withQueryParams = true)
|
|
{
|
|
$scheme = $this->server->get('REQUEST_SCHEME');
|
|
$hostAndPort = $this->server->get('HTTP_HOST');
|
|
$requestUri = $this->server->get('REQUEST_URI');
|
|
|
|
$fullUriWithQueryParams = sprintf('%s://%s%s', $scheme, $hostAndPort, $requestUri);
|
|
if ($withQueryParams === true) {
|
|
return $fullUriWithQueryParams;
|
|
}
|
|
|
|
/*
|
|
* Nachfolgend werden die GET-Parameter aus der Uri entfernt
|
|
*/
|
|
|
|
$offset = strpos($fullUriWithQueryParams, '?');
|
|
$fullUriWithoutQueryParams = $offset !== false
|
|
? substr_replace($fullUriWithQueryParams, '', $offset)
|
|
: $fullUriWithQueryParams;
|
|
|
|
// Query-String zerlegen
|
|
$queryString = $this->server->get('QUERY_STRING');
|
|
parse_str($queryString, $queryParts);
|
|
|
|
/** @see /www/api/docs.html#failsafe */
|
|
if (isset($queryParts['path'])) {
|
|
return $fullUriWithoutQueryParams . '?path=' . $queryParts['path'];
|
|
}
|
|
|
|
return $fullUriWithoutQueryParams;
|
|
}
|
|
|
|
/**
|
|
* Beispiel-Failsafe-Uri: /api/index.php?path=/v1/adressen
|
|
*
|
|
* @see /www/api/docs.html#failsafe
|
|
*
|
|
* @return bool
|
|
*/
|
|
public function isFailsafeUri()
|
|
{
|
|
$queryString = $this->server->get('QUERY_STRING');
|
|
parse_str($queryString, $queryParts);
|
|
|
|
return isset($queryParts['path']);
|
|
}
|
|
|
|
/**
|
|
* @return string|null [json|xml|html|...] oder null wenn nicht gesetzt
|
|
*/
|
|
public function getContentType()
|
|
{
|
|
$contentTypeRaw = $this->headers->get('Content-Type');
|
|
if (null === $contentTypeRaw) {
|
|
return null;
|
|
}
|
|
|
|
$typeParts = explode('/', strtolower($contentTypeRaw));
|
|
|
|
return $typeParts[1];
|
|
}
|
|
|
|
/**
|
|
* @return string
|
|
*/
|
|
public function getContent()
|
|
{
|
|
if (null === $this->content) {
|
|
$this->content = file_get_contents('php://input');
|
|
}
|
|
|
|
return !empty($this->content) ? $this->content : '';
|
|
}
|
|
|
|
/**
|
|
* @param string $content
|
|
*/
|
|
public function setContent($content)
|
|
{
|
|
$this->content = (string)$content;
|
|
}
|
|
|
|
/**
|
|
* @return array
|
|
*/
|
|
public function getAcceptableContentTypes()
|
|
{
|
|
if (null === $this->acceptableContentTypes) {
|
|
$acceptHeaderRaw = $this->headers->get('Accept');
|
|
$acceptParts = explode(',', $acceptHeaderRaw);
|
|
|
|
$acceptable = [];
|
|
foreach ($acceptParts as $acceptPart) {
|
|
if ($pos = strpos($acceptPart, ';')) {
|
|
// Priorität abschneiden
|
|
$acceptPart = substr($acceptPart, 0, $pos);
|
|
}
|
|
$acceptable[] = $acceptPart;
|
|
}
|
|
|
|
$this->acceptableContentTypes = $acceptable;
|
|
}
|
|
|
|
return $this->acceptableContentTypes;
|
|
}
|
|
|
|
/**
|
|
* @param string $url
|
|
*
|
|
* @return string URL ohne Query-Parameter
|
|
*/
|
|
protected function trimQueryParams($url)
|
|
{
|
|
$queryParamsOffset = strpos($url, '?');
|
|
if ($queryParamsOffset === false) {
|
|
return $url; // Keine Query-Parameter vorhanden
|
|
}
|
|
|
|
return substr($url, 0, $queryParamsOffset);
|
|
}
|
|
}
|