From 9cac7f37fc2e307a1430757cf3a116f3f6b87bbd Mon Sep 17 00:00:00 2001 From: Duncan McClean <19637309+duncanmcclean@users.noreply.github.com> Date: Thu, 8 Apr 2021 17:22:48 +0100 Subject: [PATCH] Fix 404 error when URLs have both ending slash and query parameters (#3494) --- src/Http/Controllers/FrontendController.php | 12 +- tests/FrontendTest.php | 117 ++++++++++++++++++++ 2 files changed, 122 insertions(+), 7 deletions(-) diff --git a/src/Http/Controllers/FrontendController.php b/src/Http/Controllers/FrontendController.php index d5d13d5100..56c2e4d543 100644 --- a/src/Http/Controllers/FrontendController.php +++ b/src/Http/Controllers/FrontendController.php @@ -29,13 +29,7 @@ public function __construct() */ public function index(Request $request) { - $url = Site::current()->relativePath( - str_finish($request->getUri(), '/') - ); - - if ($url === '') { - $url = '/'; - } + $url = Site::current()->relativePath($request->getUri()); if (Statamic::isAmpRequest()) { $url = str_after($url, '/'.config('statamic.amp.route')); @@ -45,6 +39,10 @@ public function index(Request $request) $url = substr($url, 0, strpos($url, '?')); } + if (Str::endsWith($url, '/') && Str::length($url) > 1) { + $url = rtrim($url, '/'); + } + if ($data = Data::findByUri($url, Site::current()->handle())) { return $data; } diff --git a/tests/FrontendTest.php b/tests/FrontendTest.php index 5aa2911145..87eb914e9b 100644 --- a/tests/FrontendTest.php +++ b/tests/FrontendTest.php @@ -76,6 +76,123 @@ public function page_is_displayed_with_query_string() $this->assertEquals('

The About Page

This is the about page.

', trim($response->content())); } + /** @test */ + public function page_is_displayed_with_ending_slash() + { + $this->withStandardBlueprints(); + $this->withFakeViews(); + $this->viewShouldReturnRaw('layout', '{{ template_content }}'); + $this->viewShouldReturnRaw('some_template', '

{{ title }}

{{ content }}

'); + + $page = $this->createPage('about', [ + 'with' => [ + 'title' => 'The About Page', + 'content' => 'This is the about page.', + 'template' => 'some_template', + ], + ]); + + $response = $this->get('/about/')->assertStatus(200); + + $this->assertEquals('

The About Page

This is the about page.

', trim($response->content())); + } + + /** @test */ + public function page_is_displayed_with_query_string_and_ending_slash() + { + $this->withStandardBlueprints(); + $this->withFakeViews(); + $this->viewShouldReturnRaw('layout', '{{ template_content }}'); + $this->viewShouldReturnRaw('some_template', '

{{ title }}

{{ content }}

'); + + $page = $this->createPage('about', [ + 'with' => [ + 'title' => 'The About Page', + 'content' => 'This is the about page.', + 'template' => 'some_template', + ], + ]); + + $response = $this->get('/about/?some=querystring')->assertStatus(200); + + $this->assertEquals('

The About Page

This is the about page.

', trim($response->content())); + } + + /** @test */ + public function home_page_on_second_subdirectory_based_site_is_displayed() + { + Site::setConfig(['sites' => [ + 'english' => ['url' => 'http://localhost/', 'locale' => 'en'], + 'french' => ['url' => 'http://localhost/fr/', 'locale' => 'fr'], + ]]); + + $this->createHomePagesForTwoSites(); + + $response = $this->get('/fr')->assertStatus(200); + + $this->assertEquals('French Home', trim($response->content())); + } + + /** @test */ + public function home_page_on_second_subdirectory_based_site_is_displayed_with_ending_slash() + { + Site::setConfig(['sites' => [ + 'english' => ['url' => 'http://localhost/', 'locale' => 'en'], + 'french' => ['url' => 'http://localhost/fr/', 'locale' => 'fr'], + ]]); + + $this->createHomePagesForTwoSites(); + + $response = $this->get('/fr/')->assertStatus(200); + + $this->assertEquals('French Home', trim($response->content())); + } + + /** @test */ + public function home_page_on_second_domain_site_is_displayed() + { + Site::setConfig(['sites' => [ + 'english' => ['url' => 'http://localhost/', 'locale' => 'en'], + 'french' => ['url' => 'http://anotherhost.com/', 'locale' => 'fr'], + ]]); + + $this->createHomePagesForTwoSites(); + + $response = $this->get('http://anotherhost.com')->assertStatus(200); + + $this->assertEquals('French Home', trim($response->content())); + } + + /** @test */ + public function home_page_on_second_domain_site_is_displayed_with_ending_slash() + { + Site::setConfig(['sites' => [ + 'english' => ['url' => 'http://localhost/', 'locale' => 'en'], + 'french' => ['url' => 'http://anotherhost.com/', 'locale' => 'fr'], + ]]); + + $this->createHomePagesForTwoSites(); + + $response = $this->get('http://anotherhost.com/')->assertStatus(200); + + $this->assertEquals('French Home', trim($response->content())); + } + + private function createHomePagesForTwoSites() + { + $this->withStandardBlueprints(); + $this->withoutExceptionHandling(); + $this->withStandardFakeViews(); + + $c = tap(Collection::make('pages')->sites(['english', 'french'])->routes('{slug}')->structureContents(['root' => true]))->save(); + + EntryFactory::id('1')->locale('english')->slug('home')->collection('pages')->data(['content' => 'Home'])->create(); + EntryFactory::id('2')->locale('french')->slug('french-home')->collection('pages')->data(['content' => 'French Home'])->create(); + + $c->structure()->in('english')->tree([['entry' => '1']])->save(); + $c->structure()->in('french')->tree([['entry' => '2']])->save(); + } + /** @test */ public function drafts_are_not_visible() {