Skip to content

Commit 9d4ae06

Browse files
committed
Refactor + remove urldecode from 0776925
1 parent 0776925 commit 9d4ae06

File tree

2 files changed

+49
-122
lines changed

2 files changed

+49
-122
lines changed

src/Response.php

Lines changed: 21 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ public function toResponse($request)
109109
[
110110
'component' => $this->component,
111111
'props' => $props,
112-
'url' => $this->getRequestUrl($request),
112+
'url' => $this->getUrl($request),
113113
'version' => $this->version,
114114
'clearHistory' => $this->clearHistory,
115115
'encryptHistory' => $this->encryptHistory,
@@ -361,28 +361,27 @@ public function isPartial(Request $request): bool
361361
}
362362

363363
/**
364-
* Get the request URL with proper handling of proxy prefixes and trailing slashes.
364+
* Get the URL from the request (without the scheme and host) while preserving the trailing slash if it exists.
365365
*/
366-
protected function getRequestUrl(Request $request): string
366+
protected function getUrl(Request $request): string
367367
{
368-
// Get the original request URI which should already contain any base path
369-
$originalUri = $request->getRequestUri();
370-
371-
// Handle X-Forwarded-Prefix header for proxy setups
372-
if ($prefix = $request->header('X_FORWARDED_PREFIX')) {
373-
// Only add the prefix if it's not already at the start of the URI
374-
if (!str_starts_with($originalUri, $prefix)) {
375-
$originalUri = $prefix . $originalUri;
376-
}
377-
}
378-
379-
// Decode the query string portion for better readability
380-
if (str_contains($originalUri, '?')) {
381-
list($path, $query) = explode('?', $originalUri, 2);
382-
$query = urldecode($query);
383-
return $path . '?' . $query;
384-
}
385-
386-
return $originalUri;
368+
$url = Str::start(Str::after($request->fullUrl(), $request->getSchemeAndHttpHost()), '/');
369+
370+
$rawUri = Str::before($request->getRequestUri(), '?');
371+
372+
return Str::endsWith($rawUri, '/') ? $this->finishUrlWithTrailingSlash($url) : $url;
373+
}
374+
375+
/**
376+
* Ensure the URL has a trailing slash before the query string (if it exists).
377+
*/
378+
protected function finishUrlWithTrailingSlash(string $url): string
379+
{
380+
// Make sure the relative URL ends with a trailing slash and re-append the query string if it exists.
381+
$urlWithoutQueryWithTrailingSlash = Str::finish(Str::before($url, '?'), '/');
382+
383+
return str_contains($url, '?')
384+
? $urlWithoutQueryWithTrailingSlash.'?'.Str::after($url, '?')
385+
: $urlWithoutQueryWithTrailingSlash;
387386
}
388387
}

tests/ResponseTest.php

Lines changed: 28 additions & 100 deletions
Original file line numberDiff line numberDiff line change
@@ -32,18 +32,6 @@ public function test_can_macro(): void
3232
$this->assertEquals('bar', $response->foo());
3333
}
3434

35-
public function test_the_page_url_is_not_encoded(): void
36-
{
37-
$request = Request::create('/product/123', 'GET', ['value' => 'te/st']);
38-
$request->headers->add(['X-Inertia' => 'true']);
39-
40-
$response = new Response('Product/Show', []);
41-
$response = $response->toResponse($request);
42-
$page = $response->getData();
43-
44-
$this->assertSame('/product/123?value=te/st', $page->url);
45-
}
46-
4735
public function test_server_response(): void
4836
{
4937
$request = Request::create('/user/123', 'GET');
@@ -839,112 +827,52 @@ public function test_the_page_url_doesnt_double_up(): void
839827

840828
$this->assertSame('/subpath/product/123', $page->url);
841829
}
842-
843-
public function test_trailing_slashes_in_url_are_preserved(): void
830+
831+
public function test_trailing_slashes_in_a_url_are_preserved(): void
844832
{
845-
// Test with trailing slash in the URL
846-
$request = Request::create('/categories/', 'GET');
833+
$request = Request::create('/users/', 'GET');
847834
$request->headers->add(['X-Inertia' => 'true']);
848-
849-
$response = new Response('Category/Index', []);
850-
$response = $response->toResponse($request);
851-
$page = $response->getData();
852-
853-
$this->assertSame('/categories/', $page->url);
854-
855-
// Test with trailing slash and query parameters
856-
$request = Request::create('/categories/?page=1&sort=name', 'GET');
857-
$request->headers->add(['X-Inertia' => 'true']);
858-
859-
$response = new Response('Category/Index', []);
860-
$response = $response->toResponse($request);
861-
$page = $response->getData();
862-
863-
$this->assertSame('/categories/?page=1&sort=name', $page->url);
864-
865-
// Test with trailing slash and proxy prefix
866-
$request = Request::create('/categories/', 'GET');
867-
$request->headers->set('X_FORWARDED_PREFIX', '/admin');
868-
$request->headers->add(['X-Inertia' => 'true']);
869-
870-
$response = new Response('Category/Index', []);
835+
836+
$response = new Response('User/Index', []);
871837
$response = $response->toResponse($request);
872838
$page = $response->getData();
873-
874-
$this->assertSame('/admin/categories/', $page->url);
839+
840+
$this->assertSame('/users/', $page->url);
875841
}
876-
877-
public function test_non_trailing_slashes_in_url_work_correctly(): void
842+
843+
public function test_trailing_slashes_in_a_url_with_query_parameters_are_preserved(): void
878844
{
879-
// Test with non-trailing slash in the URL
880-
$request = Request::create('/categories', 'GET');
845+
$request = Request::create('/users/?page=1&sort=name', 'GET');
881846
$request->headers->add(['X-Inertia' => 'true']);
882-
883-
$response = new Response('Category/Index', []);
884-
$response = $response->toResponse($request);
885-
$page = $response->getData();
886-
887-
$this->assertSame('/categories', $page->url);
888-
889-
// Test with non-trailing slash and query parameters
890-
$request = Request::create('/categories?page=1&sort=name', 'GET');
891-
$request->headers->add(['X-Inertia' => 'true']);
892-
893-
$response = new Response('Category/Index', []);
894-
$response = $response->toResponse($request);
895-
$page = $response->getData();
896-
897-
$this->assertSame('/categories?page=1&sort=name', $page->url);
898-
899-
// Test with non-trailing slash and proxy prefix
900-
$request = Request::create('/categories', 'GET');
901-
$request->headers->set('X_FORWARDED_PREFIX', '/admin');
902-
$request->headers->add(['X-Inertia' => 'true']);
903-
904-
$response = new Response('Category/Index', []);
847+
848+
$response = new Response('User/Index', []);
905849
$response = $response->toResponse($request);
906850
$page = $response->getData();
907-
908-
$this->assertSame('/admin/categories', $page->url);
851+
852+
$this->assertSame('/users/?page=1&sort=name', $page->url);
909853
}
910-
911-
public function test_url_with_slashes_in_query_params(): void
854+
855+
public function test_a_url_without_trailing_slash_is_resolved_correctly(): void
912856
{
913-
// Test with forward slashes in query parameters
914-
$request = Request::create('/product/123?value=te/st', 'GET');
857+
$request = Request::create('/users', 'GET');
915858
$request->headers->add(['X-Inertia' => 'true']);
916-
917-
$response = new Response('Product/Show', []);
859+
860+
$response = new Response('User/Index', []);
918861
$response = $response->toResponse($request);
919862
$page = $response->getData();
920-
921-
// Forward slashes should be preserved, not encoded as %2F
922-
$this->assertSame('/product/123?value=te/st', $page->url);
863+
864+
$this->assertSame('/users', $page->url);
923865
}
924-
925-
public function test_url_with_ampersands_in_query_params(): void
866+
867+
public function test_a_url_without_trailing_slash_and_query_parameters_is_resolved_correctly(): void
926868
{
927-
// Test normal query parameters with & as separator
928-
$request = Request::create('/families?search=jonathan&amy=test', 'GET');
869+
$request = Request::create('/users?page=1&sort=name', 'GET');
929870
$request->headers->add(['X-Inertia' => 'true']);
930-
931-
$response = new Response('Family/Index', []);
932-
$response = $response->toResponse($request);
933-
$page = $response->getData();
934-
935-
// Check that the URL contains both parameters properly separated by &
936-
$this->assertStringContainsString('search=jonathan', $page->url);
937-
$this->assertStringContainsString('amy=test', $page->url);
938-
939-
// Test encoded ampersand within a parameter value
940-
$request = Request::create('/families?search=jonathan%26amy', 'GET');
941-
$request->headers->add(['X-Inertia' => 'true']);
942-
943-
$response = new Response('Family/Index', []);
871+
872+
$response = new Response('User/Index', []);
944873
$response = $response->toResponse($request);
945874
$page = $response->getData();
946-
947-
// The & should be decoded in the parameter value
948-
$this->assertSame('/families?search=jonathan&amy', $page->url);
875+
876+
$this->assertSame('/users?page=1&sort=name', $page->url);
949877
}
950878
}

0 commit comments

Comments
 (0)