I created a middleware class named PathParser which runs on every request. The purpose is to handle requests for "vanity URL paths" that we allowed users to create in our pre-Laravel vanilla PHP app. For example: A user created a URL path such as: http://example.com/i-love-this-place
What PathParser does is to check for 404 responses, and then look to see if the URL path matched one of our old vanity paths. Like this:
class PathParser
{
public function handle($request, Closure $next, $guard = null)
{
$next_response = $next($request);
$status_code = $next_response->getStatusCode();
if ($status_code === 404) {
$script_url = $request->server("SCRIPT_URL");
$vanity_controller = new VanityController();
$found_vanity_id = Search::findVanityPath($script_url);
if (!empty($found_vanity_id)) {
$next_response = response()->make($vanity_controller->one($found_vanity_id));
}
}
return $next_response;
}
}
Assume the following:
A user has never created a URL path that would conflict with any route
I must support a number of existing (pre-Laravel) vanity URL paths that are out in the wild -- posted to social media and so on.
In Kernel.php, I have the following:
protected $middleware = [
\Illuminate\Foundation\Http\Middleware\CheckForMaintenanceMode::class,
\App\Http\Middleware\PathParser::class,
//\Illuminate\Session\Middleware\StartSession::class,
//\Illuminate\View\Middleware\ShareErrorsFromSession::class,
];
protected $middlewareGroups = [
'web' => [
\App\Http\Middleware\EncryptCookies::class,
\Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
\Illuminate\Session\Middleware\StartSession::class,
\Illuminate\View\Middleware\ShareErrorsFromSession::class,
\App\Http\Middleware\VerifyCsrfToken::class,
\Illuminate\Routing\Middleware\SubstituteBindings::class,
],
];
In the $middleware array I tried added StartSession and ShareErrorsFromSession (uncommenting the 2 lines above), and this works partially. But with two major problems:
- Auth::user is null, even for requests made to vanity paths by logged in users
- $errors no longer gets populated on form submission (such as on the registration and login pages) when a user submits incorrect/invalid information
Is there a way both to check the route on all requests and get ahold of the authenticated user, also preserving $errors?
I have a feeling I don't understand the request lifecycle well enough to succeed. But maybe there is a way?
If it's not possible to do what I require, then use of 302 redirection to a standardized prefixed path (such as http://example.com/vanity/i-love-this-place) is a fine solution. But I'm hoping there is another means.
A couple suggestions:
If you don't need auth/sessions/etc, then you can just handle the
Symfony\Component\HttpKernel\Exception\NotFoundHttpException
exception inside your application's exception handler.In
app/Exceptions/Handler.php
, modify therender()
method to look something like:If you do need auth/sessions/etc, I would suggest creating a "catchall" route at the end of your routes file. For example, as the very last line in your
routes/web.php
file, put:Then, inside your
VanityController
, have ahandle
method that looks like: