diff --git a/src/Middleware.php b/src/Middleware.php index fafc136..4a07f7f 100644 --- a/src/Middleware.php +++ b/src/Middleware.php @@ -66,9 +66,16 @@ public function handle(Request $request, Closure $next) } try { - $response = $this->validate($request, $next); + $requestPath = $request->route()->uri(); + $pathItem = $this->pathItem($requestPath, $request->method()); } catch (InvalidPathException|MalformedSpecException|MissingSpecException|TypeErrorException|UnresolvableReferenceException $exception) { $this->spectator->captureRequestValidation($exception); + + return $next($request); + } + + try { + return $this->validate($request, $next, $requestPath, $pathItem); } catch (\Throwable $exception) { if ($this->exceptionHandler->shouldReport($exception)) { return $this->formatResponse($exception, 500); @@ -76,8 +83,6 @@ public function handle(Request $request, Closure $next) throw $exception; } - - return $response; } /** @@ -100,22 +105,12 @@ protected function formatResponse($exception, $code): JsonResponse /** * @param Request $request * @param Closure $next + * @param string $requestPath + * @param PathItem $pathItem * @return mixed - * - * @throws InvalidPathException - * @throws MalformedSpecException - * @throws MissingSpecException - * @throws TypeErrorException - * @throws UnresolvableReferenceException - * @throws IOException - * @throws InvalidJsonPointerSyntaxException */ - protected function validate(Request $request, Closure $next) + protected function validate(Request $request, Closure $next, string $requestPath, PathItem $pathItem) { - $request_path = $request->route()->uri(); - - $pathItem = $this->pathItem($request_path, $request->method()); - try { RequestValidator::validate( $request, @@ -130,7 +125,7 @@ protected function validate(Request $request, Closure $next) try { ResponseValidator::validate( - $request_path, + $requestPath, $response, $pathItem->{strtolower($request->method())}, $this->version @@ -143,8 +138,8 @@ protected function validate(Request $request, Closure $next) } /** - * @param $request_path - * @param $request_method + * @param $requestPath + * @param $requestMethod * @return PathItem * * @throws InvalidPathException @@ -155,10 +150,10 @@ protected function validate(Request $request, Closure $next) * @throws IOException * @throws InvalidJsonPointerSyntaxException */ - protected function pathItem($request_path, $request_method): PathItem + protected function pathItem($requestPath, $requestMethod): PathItem { - if (! Str::startsWith($request_path, '/')) { - $request_path = '/'.$request_path; + if (! Str::startsWith($requestPath, '/')) { + $requestPath = '/'.$requestPath; } $openapi = $this->spectator->resolve(); @@ -166,19 +161,19 @@ protected function pathItem($request_path, $request_method): PathItem $this->version = $openapi->openapi; foreach ($openapi->paths as $path => $pathItem) { - if ($this->resolvePath($path) === $request_path) { + if ($this->resolvePath($path) === $requestPath) { $methods = array_keys($pathItem->getOperations()); // Check if the method exists for this path, and if so return the full PathItem - if (in_array(strtolower($request_method), $methods, true)) { + if (in_array(strtolower($requestMethod), $methods, true)) { return $pathItem; } - throw new InvalidPathException("[{$request_method}] not a valid method for [{$request_path}].", 405); + throw new InvalidPathException("[{$requestMethod}] not a valid method for [{$requestPath}].", 405); } } - throw new InvalidPathException("Path [{$request_method} {$request_path}] not found in spec.", 404); + throw new InvalidPathException("Path [{$requestMethod} {$requestPath}] not found in spec.", 404); } /** diff --git a/tests/AssertionsTest.php b/tests/AssertionsTest.php index f679bf9..735315b 100644 --- a/tests/AssertionsTest.php +++ b/tests/AssertionsTest.php @@ -2,6 +2,7 @@ namespace Spectator\Tests; +use ErrorException; use Illuminate\Support\Facades\Config; use Illuminate\Support\Facades\Route; use Illuminate\Validation\ValidationException; @@ -37,6 +38,46 @@ public function test_asserts_invalid_path() ->assertValidationMessage('Path [GET /invalid] not found in spec.'); } + public function test_fails_asserts_invalid_path() + { + $this->expectException(ErrorException::class); + $this->expectExceptionMessage('Path [GET /invalid] not found in spec.'); + + Route::get('/invalid', function () { + return [ + [ + 'id' => 1, + 'name' => 'Jim', + 'email' => 'test@test.test', + ], + ]; + })->middleware(Middleware::class); + + $this->getJson('/invalid') + ->assertValidRequest(); + } + + public function test_fails_asserts_invalid_path_without_exception_handling() + { + $this->expectException(ErrorException::class); + $this->expectExceptionMessage('Path [GET /invalid] not found in spec.'); + + Route::get('/invalid', function () { + return [ + [ + 'id' => 1, + 'name' => 'Jim', + 'email' => 'test@test.test', + ], + ]; + })->middleware(Middleware::class); + + $this->withoutExceptionHandling(); + + $this->getJson('/invalid') + ->assertValidRequest(); + } + public function test_exception_points_to_mixin_method() { $this->expectException(\ErrorException::class);