-
Notifications
You must be signed in to change notification settings - Fork 11.7k
Description
Laravel Version
11.41.3
PHP Version
8.4.3
Database Driver & Version
No response
Description
For some reason it seems that calling /link?url=https://www.foo.com/?utm_campaign=some%20campaign in my application will fail to validate the url parameter there. Calling Str::isUrl('https://www.foo.com/?utm_campaign=some%20campaign')` directly in tinker returns true though. However, dumping $request->input('url') in the controller reveals that the %20 character there has done MIA. That also happens if I use + as a space encoder.
Steps To Reproduce
routes/web.php:
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Route;
Route::get('/link', function(Request $request) {
$request->validate(['url' => 'required|url']);
});tests/Feature/UrlValidatorTest.php:
<?php
use function Pest\Laravel\getJson;
test('passes 1', function() {
getJson('/link?url=https://www.foo.com/?utm_campaign=some%2520campaign')->assertSuccessful();
});
test('fails 1', function() {
getJson('/link?url=https://www.foo.com/?utm_campaign=some%20campaign')->assertSuccessful();
});
test('passes 2', function() {
getJson('/link?url=https%3A%2F%2Fwww.foo.com%2F%3Futm_campaign%3Dsome%2520campaign')->assertSuccessful();
});
test('fails 2', function() {
getJson('/link?url=https%3A%2F%2Fwww.foo.com%2F%3Futm_campaign%3Dsome%20campaign')->assertSuccessful();
});Test 2 and 4 will then fail here.
Is this supposed to fail like this? My understanding is that https://www.foo.com/?utm_campaign=some%20campaign is a completely valid URL though (and directly calling Str::isUrl('https://www.foo.com/?utm_campaign=some%20campaign') confirms that). Or should spaces in query parameters always be double encoded when passing them to Laravel for validation?
One workaround/hack is to add these lines before the validation is done:
$request->merge([
'url' => Str::replace(' ', '+', $request->input('url')),
]);Reproduction repo: https://github.com/carestad/laravel-url-validation-bug