-
Notifications
You must be signed in to change notification settings - Fork 50
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
Change the default invalid form handling to follow redirects internally #36
Conversation
This implement borrows from Inertia's dialog internal redirect. Co-authored-by: Jacob Baker-Kretzmar <[email protected]>
I'm having an issue with the Still investigating, but possibly not related to this code (because of the fact that it works with the other drivers) |
@tonysm Rather than trying to guess the form redirect URL from the route name (which simply doesn't work if you're not using those conventions), is it possible to use |
@tobyzerner nope, we can't do that. Forms can be added to any page using Turbo Frames and when they are submitted we get the referrer header sat as that page, which may not have the form. I cover that in the first video of my introduction here at 6:05 |
Ah, of course, I was only testing with full page visits. I'm having a problem with this PR as it stands. The routes in part of my application are inside a group with a name prefix, but not all of them have names. So in effect, I have routes named like:
When my POST login route throws a validation error, the redirect guesser uses I wonder if this could even be classified as a Laravel bug? Ideally routes with no name set shouldn't have their name set to their group prefix... |
It's been a while since I've touched on this PR, but the guesser here should only work if the guessed route exists. It's meant for resource routes ( |
@tonysm Sorry, let me try and clarify my issue. In Laravel, routes end up being given a name if they are inside a group with a name prefix, even if the route itself hasn't explicitly had a name set. So for this route: Route::name('prefix.')->group(function () {
Route::get('some-route', MyController::class);
}); Even though I didn't give that route a name, it's still inherited the group prefix, so its name is In any case, this PR breaks given the above behavior. If I register a few routes within a group with a name prefix: Route::name('app.')->group(function () {
Route::get('login', [LoginController::class, 'showLoginForm'])->name('login'); // name = "app.login"
Route::post('login', [LoginController::class, 'login']); // name = "app."
Route::get('other-route', MyController::class); // name = "app."
}); Now if I POST to /login, and my controller throws a validation error, TurboMiddleware will call $route = $request->route(); // the POST /login route
$name = optional($route)->getName(); // "app."
if (! $route || ! $name) { // both are present, so we continue
return null;
}
$formRouteName = $this->redirectGuesser->guess($name); // redirect guesser doesn't change the name, so it's still "app."
if (! Route::has($formRouteName)) { // there is a route called "app.", so continue
return null;
}
return route($formRouteName, $route->parameters() + request()->query()); // since other-route was registered last, the resulting URL is /other-route. A workaround is to give all of my routes names. Another workaround is to manually catch ValidationException in my controller and set its Just flagging that this is unexpected behavior introduced by this PR. Maybe better fixed upstream in Laravel though. |
Oh, interesting. Thanks for pointing it out. That's definitely not intended behavior. I'll make sure to address this before this PR gets merged. |
Confirmed that the desired behavior is to respond to invalid form submissions with a 422 status code instead of redirects (here) |
What is interesting about this error is that if I catch the validation exception and manually return a 422 from the route handler, it works. There is no issue with sessions like that. Route::post('posts', function () {
try {
$post = Post::create(request()->validate([
'title' => ['required'],
'content' => ['required'],
]));
} catch (ValidationException $e) {
view()->share('errors', $errors = new ViewErrorBag);
$errors->put('default', $e->validator->getMessageBag());
return response(
view('posts.create')->render(),
422
);
}
return redirect()->route('posts.show', $post);
})->name('posts.store'); |
Maybe if I add a validation exception handler? |
Ok, so re-sending a request through the HTTP Kernel is what triggers the error. If instead I manually create a 422 response it works fine. |
This should handle any encrypted request as well. Co-authored-by: Taylor Otwell <[email protected]>
a7bb925
to
23127fc
Compare
Changed
ValidationException
is thrown, we're following the redirects internally returning the form response body with a 422 status code, which is better handled by Turbo Native.Issue #29
This borrows from the Inertia dialog implementation.