Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 2a1a62c

Browse files
lezhnev74scaytrase
authored andcommittedJul 24, 2020
relocate exceptions to PSR15
- add a test that exceptions are thrown
1 parent 36a3352 commit 2a1a62c

8 files changed

+144
-80
lines changed
 

‎src/PSR7/Exception/InvalidRequestMessage.php ‎src/PSR15/Exception/InvalidRequestMessage.php

+3-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@
22

33
declare(strict_types=1);
44

5-
namespace League\OpenAPIValidation\PSR7\Exception;
5+
namespace League\OpenAPIValidation\PSR15\Exception;
6+
7+
use League\OpenAPIValidation\PSR7\Exception\ValidationFailed;
68

79
class InvalidRequestMessage extends ValidationFailed
810
{

‎src/PSR7/Exception/InvalidResponseMessage.php ‎src/PSR15/Exception/InvalidResponseMessage.php

+3-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@
22

33
declare(strict_types=1);
44

5-
namespace League\OpenAPIValidation\PSR7\Exception;
5+
namespace League\OpenAPIValidation\PSR15\Exception;
6+
7+
use League\OpenAPIValidation\PSR7\Exception\ValidationFailed;
68

79
class InvalidResponseMessage extends ValidationFailed
810
{

‎src/PSR7/Exception/InvalidServerRequestMessage.php ‎src/PSR15/Exception/InvalidServerRequestMessage.php

+3-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@
22

33
declare(strict_types=1);
44

5-
namespace League\OpenAPIValidation\PSR7\Exception;
5+
namespace League\OpenAPIValidation\PSR15\Exception;
6+
7+
use League\OpenAPIValidation\PSR7\Exception\ValidationFailed;
68

79
class InvalidServerRequestMessage extends ValidationFailed
810
{

‎src/PSR15/ValidationMiddleware.php

+13-2
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@
44

55
namespace League\OpenAPIValidation\PSR15;
66

7+
use League\OpenAPIValidation\PSR15\Exception\InvalidResponseMessage;
8+
use League\OpenAPIValidation\PSR15\Exception\InvalidServerRequestMessage;
9+
use League\OpenAPIValidation\PSR7\Exception\ValidationFailed;
710
use League\OpenAPIValidation\PSR7\ResponseValidator;
811
use League\OpenAPIValidation\PSR7\ServerRequestValidator;
912
use Psr\Http\Message\ResponseInterface;
@@ -34,13 +37,21 @@ public function __construct(ServerRequestValidator $requestValidator, ResponseVa
3437
public function process(ServerRequestInterface $request, RequestHandlerInterface $handler) : ResponseInterface
3538
{
3639
// 1. Validate request
37-
$matchedOASOperation = $this->requestValidator->validate($request);
40+
try {
41+
$matchedOASOperation = $this->requestValidator->validate($request);
42+
} catch (ValidationFailed $e) {
43+
throw InvalidServerRequestMessage::because($e);
44+
}
3845

3946
// 2. Process request
4047
$response = $handler->handle($request);
4148

4249
// 3. Validate response
43-
$this->responseValidator->validate($matchedOASOperation, $response);
50+
try {
51+
$this->responseValidator->validate($matchedOASOperation, $response);
52+
} catch (ValidationFailed $e) {
53+
throw InvalidResponseMessage::because($e);
54+
}
4455

4556
return $response;
4657
}

‎src/PSR7/RequestValidator.php

+28-33
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
namespace League\OpenAPIValidation\PSR7;
66

77
use cebe\openapi\spec\OpenApi;
8-
use League\OpenAPIValidation\PSR7\Exception\InvalidRequestMessage;
98
use League\OpenAPIValidation\PSR7\Exception\MultipleOperationsMismatchForRequest;
109
use League\OpenAPIValidation\PSR7\Exception\NoOperation;
1110
use League\OpenAPIValidation\PSR7\Exception\ValidationFailed;
@@ -54,44 +53,40 @@ public function getSchema() : OpenApi
5453
*/
5554
public function validate(RequestInterface $request) : OperationAddress
5655
{
57-
try {
58-
$path = $request->getUri()->getPath();
59-
$method = strtolower($request->getMethod());
60-
61-
// 0. Find matching operations
62-
// If there is only one - then proceed with checking
63-
// If there are multiple candidates, then check each one, if all fail - we don't know which one supposed to be the one, so we need to throw an exception like
64-
// "This request matched operations A,B and C, but mismatched its schemas."
65-
$matchingOperationsAddrs = $this->findMatchingOperations($request);
66-
67-
if (! $matchingOperationsAddrs) {
68-
throw NoOperation::fromPathAndMethod($path, $method);
69-
}
56+
$path = $request->getUri()->getPath();
57+
$method = strtolower($request->getMethod());
7058

71-
// Single match is the most desirable variant, because we reduce ambiguity down to zero
72-
if (count($matchingOperationsAddrs) === 1) {
73-
$this->validator->validate($matchingOperationsAddrs[0], $request);
59+
// 0. Find matching operations
60+
// If there is only one - then proceed with checking
61+
// If there are multiple candidates, then check each one, if all fail - we don't know which one supposed to be the one, so we need to throw an exception like
62+
// "This request matched operations A,B and C, but mismatched its schemas."
63+
$matchingOperationsAddrs = $this->findMatchingOperations($request);
7464

75-
return $matchingOperationsAddrs[0];
76-
}
65+
if (! $matchingOperationsAddrs) {
66+
throw NoOperation::fromPathAndMethod($path, $method);
67+
}
7768

78-
// there are multiple matching operations, this is bad, because if none of them match the message
79-
// then we cannot say reliably which one intended to match
80-
foreach ($matchingOperationsAddrs as $matchedAddr) {
81-
try {
82-
$this->validator->validate($matchedAddr, $request);
69+
// Single match is the most desirable variant, because we reduce ambiguity down to zero
70+
if (count($matchingOperationsAddrs) === 1) {
71+
$this->validator->validate($matchingOperationsAddrs[0], $request);
8372

84-
return $matchedAddr; // Good, operation matched and request is valid against it, stop here
85-
} catch (Throwable $e) {
86-
// that operation did not match
87-
}
88-
}
73+
return $matchingOperationsAddrs[0];
74+
}
75+
76+
// there are multiple matching operations, this is bad, because if none of them match the message
77+
// then we cannot say reliably which one intended to match
78+
foreach ($matchingOperationsAddrs as $matchedAddr) {
79+
try {
80+
$this->validator->validate($matchedAddr, $request);
8981

90-
// no operation matched at all...
91-
throw MultipleOperationsMismatchForRequest::fromMatchedAddrs($matchingOperationsAddrs);
92-
} catch (ValidationFailed $e) {
93-
throw InvalidRequestMessage::because($e);
82+
return $matchedAddr; // Good, operation matched and request is valid against it, stop here
83+
} catch (Throwable $e) {
84+
// that operation did not match
85+
}
9486
}
87+
88+
// no operation matched at all...
89+
throw MultipleOperationsMismatchForRequest::fromMatchedAddrs($matchingOperationsAddrs);
9590
}
9691

9792
/**

‎src/PSR7/ResponseValidator.php

+4-9
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
namespace League\OpenAPIValidation\PSR7;
66

77
use cebe\openapi\spec\OpenApi;
8-
use League\OpenAPIValidation\PSR7\Exception\InvalidResponseMessage;
98
use League\OpenAPIValidation\PSR7\Exception\ValidationFailed;
109
use League\OpenAPIValidation\PSR7\Validators\BodyValidator\BodyValidator;
1110
use League\OpenAPIValidation\PSR7\Validators\HeadersValidator;
@@ -39,13 +38,9 @@ public function getSchema() : OpenApi
3938
*/
4039
public function validate(OperationAddress $opAddr, ResponseInterface $response) : void
4140
{
42-
try {
43-
$this->validator->validate(
44-
new ResponseAddress($opAddr->path(), $opAddr->method(), $response->getStatusCode()),
45-
$response
46-
);
47-
} catch (ValidationFailed $e) {
48-
throw InvalidResponseMessage::because($e);
49-
}
41+
$this->validator->validate(
42+
new ResponseAddress($opAddr->path(), $opAddr->method(), $response->getStatusCode()),
43+
$response
44+
);
5045
}
5146
}

‎src/PSR7/ServerRequestValidator.php

+28-33
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
namespace League\OpenAPIValidation\PSR7;
66

77
use cebe\openapi\spec\OpenApi;
8-
use League\OpenAPIValidation\PSR7\Exception\InvalidServerRequestMessage;
98
use League\OpenAPIValidation\PSR7\Exception\MultipleOperationsMismatchForRequest;
109
use League\OpenAPIValidation\PSR7\Exception\NoOperation;
1110
use League\OpenAPIValidation\PSR7\Exception\ValidationFailed;
@@ -54,44 +53,40 @@ public function getSchema() : OpenApi
5453
*/
5554
public function validate(ServerRequestInterface $serverRequest) : OperationAddress
5655
{
57-
try {
58-
$path = $serverRequest->getUri()->getPath();
59-
$method = strtolower($serverRequest->getMethod());
60-
61-
// 0. Find matching operations
62-
// If there is only one - then proceed with checking
63-
// If there are multiple candidates, then check each one, if all fail - we don't know which one supposed to be the one, so we need to throw an exception like
64-
// "This request matched operations A,B and C, but mismatched its schemas."
65-
$matchingOperationsAddrs = $this->findMatchingOperations($serverRequest);
66-
67-
if (! $matchingOperationsAddrs) {
68-
throw NoOperation::fromPathAndMethod($path, $method);
69-
}
56+
$path = $serverRequest->getUri()->getPath();
57+
$method = strtolower($serverRequest->getMethod());
7058

71-
// Single match is the most desirable variant, because we reduce ambiguity down to zero
72-
if (count($matchingOperationsAddrs) === 1) {
73-
$this->validator->validate($matchingOperationsAddrs[0], $serverRequest);
59+
// 0. Find matching operations
60+
// If there is only one - then proceed with checking
61+
// If there are multiple candidates, then check each one, if all fail - we don't know which one supposed to be the one, so we need to throw an exception like
62+
// "This request matched operations A,B and C, but mismatched its schemas."
63+
$matchingOperationsAddrs = $this->findMatchingOperations($serverRequest);
7464

75-
return $matchingOperationsAddrs[0];
76-
}
65+
if (! $matchingOperationsAddrs) {
66+
throw NoOperation::fromPathAndMethod($path, $method);
67+
}
7768

78-
// there are multiple matching operations, this is bad, because if none of them match the message
79-
// then we cannot say reliably which one intended to match
80-
foreach ($matchingOperationsAddrs as $matchedAddr) {
81-
try {
82-
$this->validator->validate($matchedAddr, $serverRequest);
69+
// Single match is the most desirable variant, because we reduce ambiguity down to zero
70+
if (count($matchingOperationsAddrs) === 1) {
71+
$this->validator->validate($matchingOperationsAddrs[0], $serverRequest);
8372

84-
return $matchedAddr; // Good, operation matched and request is valid against it, stop here
85-
} catch (Throwable $e) {
86-
// that operation did not match
87-
}
88-
}
73+
return $matchingOperationsAddrs[0];
74+
}
75+
76+
// there are multiple matching operations, this is bad, because if none of them match the message
77+
// then we cannot say reliably which one intended to match
78+
foreach ($matchingOperationsAddrs as $matchedAddr) {
79+
try {
80+
$this->validator->validate($matchedAddr, $serverRequest);
8981

90-
// no operation matched at all...
91-
throw MultipleOperationsMismatchForRequest::fromMatchedAddrs($matchingOperationsAddrs);
92-
} catch (ValidationFailed $e) {
93-
throw InvalidServerRequestMessage::because($e);
82+
return $matchedAddr; // Good, operation matched and request is valid against it, stop here
83+
} catch (Throwable $e) {
84+
// that operation did not match
85+
}
9486
}
87+
88+
// no operation matched at all...
89+
throw MultipleOperationsMismatchForRequest::fromMatchedAddrs($matchingOperationsAddrs);
9590
}
9691

9792
/**
+62
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace League\OpenAPIValidation\Tests\PSR15;
6+
7+
use GuzzleHttp\Psr7\Response;
8+
use GuzzleHttp\Psr7\ServerRequest;
9+
use League\OpenAPIValidation\PSR15\Exception\InvalidResponseMessage;
10+
use League\OpenAPIValidation\PSR15\Exception\InvalidServerRequestMessage;
11+
use League\OpenAPIValidation\PSR15\ValidationMiddleware;
12+
use League\OpenAPIValidation\PSR7\ValidatorBuilder;
13+
use League\OpenAPIValidation\Tests\PSR7\BaseValidatorTest;
14+
use Psr\Http\Message\ServerRequestInterface;
15+
use Psr\Http\Server\RequestHandlerInterface;
16+
17+
class ValidationMiddlewareTest extends BaseValidatorTest
18+
{
19+
/** @return array<mixed> data sets for tests */
20+
public function dataProvider() : array
21+
{
22+
return [
23+
// Bad Server Request
24+
[
25+
new ServerRequest('get', '/unknown'),
26+
$this->createMock(RequestHandlerInterface::class),
27+
InvalidServerRequestMessage::class,
28+
],
29+
// Bad Response
30+
[
31+
$this->makeGoodServerRequest('/read', 'get'),
32+
(function () {
33+
$mock = $this->createMock(RequestHandlerInterface::class);
34+
$mock
35+
->expects($this->once())
36+
->method('handle')
37+
->willReturn(new Response());
38+
39+
return $mock;
40+
})(),
41+
InvalidResponseMessage::class,
42+
],
43+
];
44+
}
45+
46+
/** @dataProvider dataProvider */
47+
public function testItReturnsExpectedException(
48+
ServerRequestInterface $serverRequest,
49+
RequestHandlerInterface $handler,
50+
string $expectedExceptionType
51+
) : void {
52+
$builder = (new ValidatorBuilder())->fromYamlFile($this->apiSpecFile);
53+
54+
$middleware = new ValidationMiddleware(
55+
$builder->getServerRequestValidator(),
56+
$builder->getResponseValidator()
57+
);
58+
59+
$this->expectException($expectedExceptionType);
60+
$middleware->process($serverRequest, $handler);
61+
}
62+
}

0 commit comments

Comments
 (0)
Please sign in to comment.