Skip to content

Commit e2641e7

Browse files
committed
Fixing url helpers to work in a subfolder.
1 parent a32ab17 commit e2641e7

3 files changed

Lines changed: 62 additions & 10 deletions

File tree

system/HTTP/IncomingRequest.php

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,11 @@ public function __construct($config, URI $uri = null, $body = 'php://input', Use
174174

175175
$this->populateHeaders();
176176

177+
// Get our current URI.
178+
// NOTE: This WILL NOT match the actual URL in the browser since for
179+
// everything this cares about (and the router, etc) is the portion
180+
// AFTER the script name. So, if hosted in a sub-folder this will
181+
// appear different than actual URL. If you need that, use current_url().
177182
$this->uri = $uri;
178183

179184
$this->detectURI($config->uriProtocol, $config->baseURL);
@@ -604,14 +609,10 @@ protected function detectURI(string $protocol, string $baseURL)
604609
// baseURL, so let's help them out.
605610
$baseURL = ! empty($baseURL) ? rtrim($baseURL, '/ ') . '/' : $baseURL;
606611

607-
// Based on our baseURL provided by the developer (if set)
612+
// Based on our baseURL provided by the developer
608613
// set our current domain name, scheme
609614
if (! empty($baseURL))
610615
{
611-
// We cannot add the path here, otherwise it's possible
612-
// that the routing will not work correctly if we are
613-
// within a sub-folder scheme. So it's modified in
614-
// the
615616
$this->uri->setScheme(parse_url($baseURL, PHP_URL_SCHEME));
616617
$this->uri->setHost(parse_url($baseURL, PHP_URL_HOST));
617618
$this->uri->setPort(parse_url($baseURL, PHP_URL_PORT));
@@ -715,7 +716,8 @@ protected function parseRequestURI(): string
715716
}
716717

717718
// parse_url() returns false if no host is present, but the path or query string
718-
// contains a colon followed by a number
719+
// contains a colon followed by a number. So we attach a dummy host since
720+
// REQUEST_URI does not include the host. This allows us to parse out the query string and path.
719721
$parts = parse_url('http://dummy' . $_SERVER['REQUEST_URI']);
720722
$query = $parts['query'] ?? '';
721723
$uri = $parts['path'] ?? '';

system/Helpers/url_helper.php

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,7 @@ function base_url($uri = '', string $protocol = null): string
139139
$url->setScheme($protocol);
140140
}
141141

142-
return (string) $url;
142+
return rtrim((string) $url, '/ ');
143143
}
144144
}
145145

@@ -159,7 +159,25 @@ function base_url($uri = '', string $protocol = null): string
159159
*/
160160
function current_url(bool $returnObject = false)
161161
{
162-
return $returnObject ? \CodeIgniter\Config\Services::request()->uri : (string) \CodeIgniter\Config\Services::request()->uri;
162+
$uri = service('request')->uri;
163+
164+
// If hosted in a sub-folder, we will have additional
165+
// segments that show up prior to the URI path we just
166+
// grabbed from the request, so add it on if necessary.
167+
$baseUri = new \CodeIgniter\HTTP\URI(config('App')->baseURL);
168+
169+
if (! empty($baseUri->getPath()))
170+
{
171+
$path = rtrim($baseUri->getPath(), '/ ') . '/' . $uri->getPath();
172+
173+
$uri->setPath($path);
174+
}
175+
176+
// Since we're basing off of the IncomingRequest URI,
177+
// we are guaranteed to have a host based on our own configs.
178+
return $returnObject
179+
? $uri
180+
: (string)$uri->setQuery('');
163181
}
164182
}
165183

tests/system/Helpers/URLHelperTest.php

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,22 @@ public function testSiteURLSegments()
167167
$this->assertEquals('http://example.com/index.php/news/local/123', site_url(['news', 'local', '123'], null, $config));
168168
}
169169

170+
public function testSiteURLInSubfolder()
171+
{
172+
$_SERVER['HTTP_HOST'] = 'example.com';
173+
$_SERVER['REQUEST_URI'] = '/foo/public/bar?baz=quip';
174+
175+
// Since we're on a CLI, we must provide our own URI
176+
$config = new App();
177+
$config->baseURL = 'http://example.com/foo/public';
178+
$request = Services::request($config);
179+
$request->uri = new URI('http://example.com/foo/public/bar');
180+
181+
Services::injectMock('request', $request);
182+
183+
$this->assertEquals('http://example.com/foo/public/bar', current_url());
184+
}
185+
170186
/**
171187
* @see https://github.com/codeigniter4/CodeIgniter4/issues/240
172188
*/
@@ -281,7 +297,7 @@ public function testBaseURLWithSegments()
281297

282298
Services::injectMock('request', $request);
283299

284-
$this->assertEquals('http://example.com/', base_url());
300+
$this->assertEquals('http://example.com', base_url());
285301
}
286302

287303
/**
@@ -330,7 +346,7 @@ public function testBaseURLHasSubfolder()
330346
Services::injectMock('request', $request);
331347

332348
$this->assertEquals('http://example.com/subfolder/foo', base_url('foo'));
333-
$this->assertEquals('http://example.com/subfolder/', base_url());
349+
$this->assertEquals('http://example.com/subfolder', base_url());
334350
}
335351

336352
//--------------------------------------------------------------------
@@ -387,6 +403,22 @@ public function testCurrentURLEquivalence()
387403
$this->assertEquals(base_url(uri_string()), current_url());
388404
}
389405

406+
public function testCurrentURLInSubfolder()
407+
{
408+
$_SERVER['HTTP_HOST'] = 'example.com';
409+
$_SERVER['REQUEST_URI'] = '/foo/public/bar?baz=quip';
410+
411+
// Since we're on a CLI, we must provide our own URI
412+
$config = new App();
413+
$config->baseURL = 'http://example.com/foo/public';
414+
$request = Services::request($config);
415+
$request->uri = new URI('http://example.com/foo/public/bar');
416+
417+
Services::injectMock('request', $request);
418+
419+
$this->assertEquals('http://example.com/foo/public/bar', current_url());
420+
}
421+
390422
//--------------------------------------------------------------------
391423
// Test previous_url
392424

0 commit comments

Comments
 (0)