-
Notifications
You must be signed in to change notification settings - Fork 10
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #43 from scaytrase/feature/routed-request-validator
Routed request validator
- Loading branch information
Showing
4 changed files
with
167 additions
and
6 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace OpenAPIValidation\PSR7; | ||
|
||
use cebe\openapi\spec\OpenApi; | ||
use OpenAPIValidation\PSR7\Exception\ValidationFailed; | ||
use OpenAPIValidation\PSR7\Validators\BodyValidator; | ||
use OpenAPIValidation\PSR7\Validators\CookiesValidator; | ||
use OpenAPIValidation\PSR7\Validators\HeadersValidator; | ||
use OpenAPIValidation\PSR7\Validators\PathValidator; | ||
use OpenAPIValidation\PSR7\Validators\QueryArgumentsValidator; | ||
use OpenAPIValidation\PSR7\Validators\SecurityValidator; | ||
use OpenAPIValidation\PSR7\Validators\ValidatorChain; | ||
use Psr\Http\Message\ServerRequestInterface; | ||
|
||
class RoutedServerRequestValidator implements ReusableSchema | ||
{ | ||
/** @var OpenApi */ | ||
protected $openApi; | ||
/** @var MessageValidator */ | ||
protected $validator; | ||
|
||
public function __construct(OpenApi $schema) | ||
{ | ||
$this->openApi = $schema; | ||
$finder = new SpecFinder($this->openApi); | ||
$this->validator = new ValidatorChain( | ||
new HeadersValidator($finder), | ||
new CookiesValidator($finder), | ||
new BodyValidator($finder), | ||
new QueryArgumentsValidator($finder), | ||
new PathValidator($finder), | ||
new SecurityValidator($finder) | ||
); | ||
} | ||
|
||
public function getSchema() : OpenApi | ||
{ | ||
return $this->openApi; | ||
} | ||
|
||
/** | ||
* @throws ValidationFailed | ||
*/ | ||
public function validate(OperationAddress $opAddr, ServerRequestInterface $serverRequest) : void | ||
{ | ||
$this->validator->validate($opAddr, $serverRequest); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,91 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace OpenAPIValidationTests\PSR7; | ||
|
||
use OpenAPIValidation\PSR7\Exception\Validation\InvalidBody; | ||
use OpenAPIValidation\PSR7\Exception\Validation\InvalidHeaders; | ||
use OpenAPIValidation\PSR7\OperationAddress; | ||
use OpenAPIValidation\PSR7\ValidatorBuilder; | ||
use function GuzzleHttp\Psr7\stream_for; | ||
use function json_encode; | ||
|
||
final class RoutedServerRequestTest extends BaseValidatorTest | ||
{ | ||
public function testItValidatesMessageGreen() : void | ||
{ | ||
$request = $this->makeGoodServerRequest('/path1', 'get'); | ||
|
||
$validator = (new ValidatorBuilder())->fromYamlFile($this->apiSpecFile)->getRoutedRequestValidator(); | ||
$validator->validate(new OperationAddress('/path1', 'get'), $request); | ||
$this->addToAssertionCount(1); | ||
} | ||
|
||
public function testItValidatesBodyGreen() : void | ||
{ | ||
$body = ['name' => 'Alex']; | ||
$request = $this->makeGoodServerRequest('/request-body', 'post') | ||
->withBody(stream_for(json_encode($body))); | ||
|
||
$validator = (new ValidatorBuilder())->fromYamlFile($this->apiSpecFile)->getRoutedRequestValidator(); | ||
$validator->validate(new OperationAddress('/request-body', 'post'), $request); | ||
$this->addToAssertionCount(1); | ||
} | ||
|
||
public function testItValidatesBodyHasInvalidPayloadRed() : void | ||
{ | ||
$addr = new OperationAddress('/request-body', 'post'); | ||
$body = ['name' => 1000]; | ||
$request = $this->makeGoodServerRequest($addr->path(), $addr->method()) | ||
->withBody(stream_for(json_encode($body))); | ||
|
||
$this->expectException(InvalidBody::class); | ||
$this->expectExceptionMessage( | ||
'Body does not match schema for content-type "application/json" for Request [post /request-body]' | ||
); | ||
|
||
$validator = (new ValidatorBuilder())->fromYamlFile($this->apiSpecFile)->getRoutedRequestValidator(); | ||
$validator->validate(new OperationAddress('/request-body', 'post'), $request); | ||
} | ||
|
||
public function testItValidatesBodyHasUnexpectedTypeRed() : void | ||
{ | ||
$addr = new OperationAddress('/request-body', 'post'); | ||
$request = $this->makeGoodServerRequest($addr->path(), $addr->method()) | ||
->withoutHeader('Content-Type') | ||
->withHeader('Content-Type', 'unexpected/content'); | ||
|
||
$this->expectException(InvalidHeaders::class); | ||
$this->expectExceptionMessage( | ||
'Content-Type "unexpected/content" is not expected for Request [post /request-body]' | ||
); | ||
|
||
$validator = (new ValidatorBuilder())->fromYamlFile($this->apiSpecFile)->getRoutedRequestValidator(); | ||
$validator->validate(new OperationAddress('/request-body', 'post'), $request); | ||
} | ||
|
||
public function testItValidatesMessageWrongHeaderValueRed() : void | ||
{ | ||
$addr = new OperationAddress('/path1', 'get'); | ||
$request = $this->makeGoodServerRequest($addr->path(), $addr->method())->withHeader('Header-A', 'wrong value'); | ||
|
||
$this->expectException(InvalidHeaders::class); | ||
$this->expectExceptionMessage('Value "wrong value" for header "Header-A" is invalid for Request [get /path1]'); | ||
|
||
$validator = (new ValidatorBuilder())->fromYamlFile($this->apiSpecFile)->getRoutedRequestValidator(); | ||
$validator->validate(new OperationAddress('/path1', 'get'), $request); | ||
} | ||
|
||
public function testItValidatesMessageMissedHeaderRed() : void | ||
{ | ||
$addr = new OperationAddress('/path1', 'get'); | ||
$request = $this->makeGoodServerRequest($addr->path(), $addr->method())->withoutHeader('Header-A'); | ||
|
||
$this->expectException(InvalidHeaders::class); | ||
$this->expectExceptionMessage('Missing required header "Header-A" for Request [get /path1]'); | ||
|
||
$validator = (new ValidatorBuilder())->fromYamlFile($this->apiSpecFile)->getRoutedRequestValidator(); | ||
$validator->validate(new OperationAddress('/path1', 'get'), $request); | ||
} | ||
} |