diff --git a/src/Control/Director.php b/src/Control/Director.php index 316148578..2f42c8c5c 100644 --- a/src/Control/Director.php +++ b/src/Control/Director.php @@ -263,7 +263,7 @@ class Director implements TemplateGlobalProvider $newVars = HTTPRequestBuilder::cleanEnvironment($newVars); // Create new request - $request = HTTPRequestBuilder::createFromVariables($newVars, $body); + $request = HTTPRequestBuilder::createFromVariables($newVars, $body, ltrim($url, '/')); if ($headers) { foreach ($headers as $k => $v) { $request->addHeader($k, $v); diff --git a/src/Control/HTTPRequestBuilder.php b/src/Control/HTTPRequestBuilder.php index 378ea3b10..0e81fc712 100644 --- a/src/Control/HTTPRequestBuilder.php +++ b/src/Control/HTTPRequestBuilder.php @@ -28,16 +28,20 @@ class HTTPRequestBuilder * * @param array $variables * @param string $input Request body + * @param string|null $url Provide specific url (relative to base) * @return HTTPRequest */ - public static function createFromVariables(array $variables, $input) + public static function createFromVariables(array $variables, $input, $url = null) { - // Remove query parameters (they're retained separately through $server['_GET'] - $url = parse_url($variables['_SERVER']['REQUEST_URI'], PHP_URL_PATH); + // Infer URL from REQUEST_URI unless explicitly provided + if (!isset($url)) { + // Remove query parameters (they're retained separately through $server['_GET'] + $url = parse_url($variables['_SERVER']['REQUEST_URI'], PHP_URL_PATH); - // Remove base folders from the URL if webroot is hosted in a subfolder - if (substr(strtolower($url), 0, strlen(BASE_URL)) === strtolower(BASE_URL)) { - $url = substr($url, strlen(BASE_URL)); + // Remove base folders from the URL if webroot is hosted in a subfolder + if (substr(strtolower($url), 0, strlen(BASE_URL)) === strtolower(BASE_URL)) { + $url = substr($url, strlen(BASE_URL)); + } } // Build request diff --git a/src/includes/constants.php b/src/includes/constants.php index 61592cadf..a53ee8c0d 100644 --- a/src/includes/constants.php +++ b/src/includes/constants.php @@ -95,6 +95,11 @@ if (!defined('BASE_URL')) { return rtrim(parse_url($base, PHP_URL_PATH), '/'); } + // Unless specified, use empty string for base in CLI + if (in_array(php_sapi_name(), ['cli', 'phpdbg'])) { + return ""; + } + // Determine the base URL by comparing SCRIPT_NAME to SCRIPT_FILENAME and getting common elements // This tends not to work on CLI $path = realpath($_SERVER['SCRIPT_FILENAME']); diff --git a/tests/php/Control/DirectorTest.php b/tests/php/Control/DirectorTest.php index fa3237545..b629317ce 100644 --- a/tests/php/Control/DirectorTest.php +++ b/tests/php/Control/DirectorTest.php @@ -929,4 +929,30 @@ class DirectorTest extends SapphireTest { $this->assertTrue(Director::is_cli(), 'is_cli should be true for PHP CLI and phpdbg'); } + + public function testMockRequest() + { + Director::config()->set('alternate_base_url', 'http://www.mysite.com/some-subdir/'); + + // Can handle root-relative $url + Director::mockRequest(function (HTTPRequest $request) { + $this->assertEquals('some-page/nested', $request->getURL()); + $this->assertEquals(1, $request->getVar('query')); + $this->assertEquals('/some-subdir/some-page/nested', $_SERVER['REQUEST_URI']); + }, '/some-subdir/some-page/nested?query=1'); + + // Can handle absolute $url + Director::mockRequest(function (HTTPRequest $request) { + $this->assertEquals('some-page/nested', $request->getURL()); + $this->assertEquals(1, $request->getVar('query')); + $this->assertEquals('/some-subdir/some-page/nested', $_SERVER['REQUEST_URI']); + }, 'http://www.mysite.com/some-subdir/some-page/nested?query=1'); + + // Can handle relative $url + Director::mockRequest(function (HTTPRequest $request) { + $this->assertEquals('some-page/nested', $request->getURL()); + $this->assertEquals(1, $request->getVar('query')); + $this->assertEquals('/some-subdir/some-page/nested', $_SERVER['REQUEST_URI']); + }, 'some-page/nested?query=1'); + } }