OpenXE/classes/Modules/Api/Http/PathInfoDetector.php

97 lines
2.9 KiB
PHP
Raw Permalink Normal View History

2021-05-21 08:49:41 +02:00
<?php
declare(strict_types=1);
namespace Xentral\Modules\Api\Http;
use Xentral\Components\Http\Request;
final class PathInfoDetector
{
/** @var Request $request */
private $request;
/**
* @param Request $request
*/
public function __construct(Request $request)
{
$this->request = $request;
}
/**
* 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|null false wenn PathInfo nicht rekonstruiert werden kann
*/
public function detect(): ?string
{
$scriptName = $this->getSafeScriptName();
if (empty($scriptName)) {
return null; // 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->request->server->get('DOCUMENT_URI');
if (!empty($docUri) && strpos($docUri, $scriptName) === 0) {
return substr($docUri, strlen($scriptName));
}
// PathInfo aus $_SERVER['PHP_SELF'] ermitteln
$phpSelf = $this->request->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->request->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 null;
}
/**
* Ermittelt $_SERVER['SCRIPT_NAME'] ohne PathInfo
*
* Unter Nginx + PHP-FPM kann(!) der $_SERVER['SCRIPT_NAME'] auch den PathInfo enthalten.
*
* @return string
*/
private function getSafeScriptName(): string
{
$scriptFilename = $this->request->server->get('SCRIPT_FILENAME');
$documentRoot = $this->request->server->get('DOCUMENT_ROOT');
if (strpos($scriptFilename, $documentRoot) === 0) {
return substr($scriptFilename, strlen($documentRoot));
}
return $this->request->server->get('SCRIPT_NAME');
}
/**
* @param string $url
*
* @return string URL ohne Query-Parameter
*/
private function trimQueryParams(string $url): string
{
$queryParamsOffset = strpos($url, '?');
if ($queryParamsOffset === false) {
return $url; // Keine Query-Parameter vorhanden
}
return substr($url, 0, $queryParamsOffset);
}
}