1313use Tempest \Router \Exceptions \ConvertsToResponse ;
1414use Tempest \Router \Exceptions \RouteBindingFailed ;
1515use Tempest \Validation \Exceptions \ValidationFailed ;
16+ use Tempest \Validation \Rule ;
17+ use Tempest \Validation \Validator ;
18+
19+ use function Tempest \get ;
20+ use function Tempest \Support \arr ;
1621
1722#[Priority(Priority::FRAMEWORK - 10 )]
1823final readonly class HandleRouteExceptionMiddleware implements HttpMiddleware
@@ -26,7 +31,9 @@ public function __invoke(Request $request, HttpMiddlewareCallable $next): Respon
2631 if ($ this ->routeConfig ->throwHttpExceptions === true ) {
2732 $ response = $ this ->forward ($ request , $ next );
2833
29- if ($ response ->status ->isServerError () || $ response ->status ->isClientError ()) {
34+ $ isValidationError = $ response ->status === Status::UNPROCESSABLE_CONTENT ;
35+
36+ if (! $ isValidationError && ($ response ->status ->isServerError () || $ response ->status ->isClientError ())) {
3037 throw new HttpRequestFailed (
3138 request: $ request ,
3239 status: $ response ->status ,
@@ -61,9 +68,15 @@ private function forward(Request $request, HttpMiddlewareCallable $next): Respon
6168 return new NotFound ();
6269 } catch (ValidationFailed $ validationException ) {
6370 if ($ this ->wantsJson ($ request )) {
71+ $ errors = arr ($ validationException ->failingRules )->map (
72+ fn (array $ failingRulesForField , string $ field ) => arr ($ failingRulesForField )->map (
73+ fn (Rule $ rule ) => get (Validator::class)->getErrorMessage ($ rule , $ field ),
74+ )->toArray (),
75+ );
76+
6477 return new Json ([
65- 'message ' => $ validationException -> getMessage () ,
66- 'errors ' => $ validationException -> errorMessages ,
78+ 'message ' => $ errors -> first ()[ 0 ] ,
79+ 'errors ' => $ errors -> toArray () ,
6780 ])->setStatus (Status::UNPROCESSABLE_CONTENT );
6881 }
6982
0 commit comments