diff --git a/src/aphront/configuration/AphrontApplicationConfiguration.php b/src/aphront/configuration/AphrontApplicationConfiguration.php --- a/src/aphront/configuration/AphrontApplicationConfiguration.php +++ b/src/aphront/configuration/AphrontApplicationConfiguration.php @@ -176,7 +176,7 @@ } $host = AphrontRequest::getHTTPHeader('Host'); - $path = $_REQUEST['__path__']; + $path = PhabricatorStartup::getRequestPath(); $application = new self(); @@ -759,7 +759,7 @@ } private static function newSelfCheckResponse() { - $path = idx($_REQUEST, '__path__', ''); + $path = PhabricatorStartup::getRequestPath(); $query = idx($_SERVER, 'QUERY_STRING', ''); $pairs = id(new PhutilQueryStringParser()) diff --git a/support/startup/PhabricatorStartup.php b/support/startup/PhabricatorStartup.php --- a/support/startup/PhabricatorStartup.php +++ b/support/startup/PhabricatorStartup.php @@ -35,6 +35,7 @@ * @task validation Validation * @task ratelimit Rate Limiting * @task phases Startup Phase Timers + * @task request-path Request Path */ final class PhabricatorStartup { @@ -47,6 +48,7 @@ private static $phases; private static $limits = array(); + private static $requestPath; /* -( Accessing Request Information )-------------------------------------- */ @@ -119,6 +121,7 @@ self::$phases = array(); self::$accessLog = null; + self::$requestPath = null; static $registered; if (!$registered) { @@ -140,7 +143,7 @@ self::normalizeInput(); - self::verifyRewriteRules(); + self::readRequestPath(); self::beginOutputCapture(); } @@ -552,17 +555,29 @@ /** - * @task validation + * @task request-path */ - private static function verifyRewriteRules() { + private static function readRequestPath() { + + // See T13575. The request path may be provided in: + // + // - the "$_GET" parameter "__path__" (normal for Apache and nginx); or + // - the "$_SERVER" parameter "REQUEST_URI" (normal for the PHP builtin + // webserver). + // + // Locate it wherever it is, and store it for later use. Note that writing + // to "$_REQUEST" here won't always work, because later code may rebuild + // "$_REQUEST" from other sources. + if (isset($_REQUEST['__path__']) && strlen($_REQUEST['__path__'])) { + self::setRequestPath($_REQUEST['__path__']); return; } + // Compatibility with PHP 5.4+ built-in web server. if (php_sapi_name() == 'cli-server') { - // Compatibility with PHP 5.4+ built-in web server. - $url = parse_url($_SERVER['REQUEST_URI']); - $_REQUEST['__path__'] = $url['path']; + $path = parse_url($_SERVER['REQUEST_URI']); + self::setRequestPath($path['path']); return; } @@ -580,6 +595,30 @@ } } + /** + * @task request-path + */ + public static function getRequestPath() { + $path = self::$requestPath; + + if ($path === null) { + self::didFatal( + 'Request attempted to access request path, but no request path is '. + 'available for this request. You may be calling web request code '. + 'from a non-request context, or your webserver may not be passing '. + 'a request path to Phabricator in a format that it understands.'); + } + + return $path; + } + + /** + * @task request-path + */ + public static function setRequestPath($path) { + self::$requestPath = $path; + } + /* -( Rate Limiting )------------------------------------------------------ */