Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fallback Route gets ignored #54338

Open
Jubeki opened this issue Jan 24, 2025 · 5 comments
Open

Fallback Route gets ignored #54338

Jubeki opened this issue Jan 24, 2025 · 5 comments

Comments

@Jubeki
Copy link
Contributor

Jubeki commented Jan 24, 2025

Laravel Version

11.39.1

PHP Version

8.3.16

Database Driver & Version

sqlite

Description

Visiting the path /%c0 on a fresh laravel application results in the fallback route being ignored and the default 404 page will instead be displayed.

This does not only apply to the fallback route but also to wildcard routes.

Route::get('/{path}', fn() => 'Test Wildcard')->where('path', '.*');
Route::fallback(fn() => 'Test Fallback');

Originally discovered in statamic: statamic/cms#11387

Steps To Reproduce

  1. Create a new Laravel Application
  2. Create the following route: Route::fallback(fn() => 'Test');
  3. Visit http://localhost:8000/awd (you will see Test, meaning the fallback route gets registered)
  4. Visit http://localhost:8000/%c0 (you will see the 404 page, which is unexpected)
@crynobone
Copy link
Member

crynobone commented Jan 24, 2025

https://onlinephp.io?s=s7EvyCjg5eLlKkssik8pzS3QKEosLy3KSUlNzk9J1VBSTTZQ0tS0BgA%2C&v=8.3.16%2C8.4.3%2C8.2.27%2C8.1.31

Looks like it is a special character that can't be parsed by PHP.

@iam-subho
Copy link

We use a fallback route for that purpose. If it is unable to parse, it should still show the fallback route. This makes more sense, I think. Can I contribute?

@Jubeki
Copy link
Contributor Author

Jubeki commented Jan 24, 2025

Looks like it is a special character that can't be parsed by PHP.

@crynobone It can be parsed, it is just an invisible character (which probably will be trimmed if that happens somewhere)

We use a fallback route for that purpose. If it is unable to parse, it should still show the fallback route. This makes more sense, I think. Can I contribute?

@iam-subho You can contribute if you want. The Laravel Framework is open-source.

I will also take a further look the upcoming days, if something can be improved in the framework.

@crynobone
Copy link
Member

@Jubeki not exactly true.

Image

And from the PHP.net documentation comment itself:

Image

@Jubeki
Copy link
Contributor Author

Jubeki commented Jan 25, 2025

Okay, you are right, I didn't consider this enough. I simply looked at the result of the Link you have given and there the length of the string was printed as 1, therefor I assumed it is an invisible character.

I at least know what the Problem is.

The fallback route, also gets registered with the wildcard .*, and then the route is simply marked as fallback.

Because the code in Illuminate\Routing\Matching\Urivalidator uses the php regex_match, the fallback routes never gets called (the same as with any wildcard route).

Here some debugging information. I added some dump statements to the UriValidator, so that I can take a look at what the values of the variables are.

<?php

namespace Illuminate\Routing\Matching;

use Illuminate\Http\Request;
use Illuminate\Routing\Route;

class UriValidator implements ValidatorInterface
{
    /**
     * Validate a given rule against a route and request.
     *
     * @param  \Illuminate\Routing\Route  $route
     * @param  \Illuminate\Http\Request  $request
     * @return bool
     */
    public function matches(Route $route, Request $request)
    {
        $path = rtrim($request->getPathInfo(), '/') ?: '/';

        if ($route->isFallback) {
            dump($route->getCompiled()->getRegex());
            dump(rawurldecode($path));
            dd($path);
        }

        return preg_match($route->getCompiled()->getRegex(), rawurldecode($path));
    }
}

This is the result:

// $route->getCompiled()->getRegex()
"{^/(?P<fallbackPlaceholder>.*)$}sDu"

// rawurldecode($path)
b""

// $path
"/%C0"

You can also clearly see that rawurldecode($path) is a binary string and not a normal string (because of the non UTF-8 character).

If we were to make changes to the behaviour, I think this should go to Laravel 12, because I am not sure how much of an impact this change has. In my opinion something should be changed, because currently the URL is broken, how about return a 400 - bad request because of the malformed url? (Not sure what the best place would be to detect this and then throw an exception.)

Or the fallback behaviour somehow needs to be adjusted, to also be called on invalid / malformed urls.

Because currently If you use the fallback method or a wildcard route to render the 404 page with some additional variables, these will not be available. (Of course you could load these variables inside the 404.blade.php file instead of using the fallback route, but it still unexpected that the fallback route does not get called.)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants