GitHub - lezhnev74/openapi-psr7-validator: It validates PSR-7 messages (HTTP req...
source link: https://github.com/lezhnev74/openapi-psr7-validator
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
README.md
OpenAPI PSR-7 Message (HTTP Request/Response) Validator
This package can validate PSR-7 messages against OpenAPI (3.0.x) specifications expressed in YAML or JSON.
Requirements
n/a
Installation
composer require lezhnev74/openapi-psr7-validator
OpenAPI (OAS) Terms
There are some specific terms that are used in the package. These terms come from OpenAPI:
specification
- an OpenAPI document describing an API, expressed in JSON or YAML filedata
- actual thing that we validate against a specification, including body and metadataschema
- the part of the specification that describes the body of the request / responsekeyword
- properties that are used to describe the instance are called key words, or schema keywordspath
- a relative path to an individual endpointoperation
- a method that we apply on the path (likeget /password
)response
- described response (includes status code, content types etc)
How To Validate
ServerRequest Message
You can validate \Psr\Http\Message\ServerRequestInterface
instance like this:
$yamlFile = "api.yaml"; $validator = new \OpenAPIValidation\PSR7\ServerRequestValidator( \cebe\openapi\Reader::readFromYamlFile($yamlFile) ); $validator->validate($request);
Response Message
Validation of \Psr\Http\Message\ResponseInterface
is a bit more complicated
. Because you need not only YAML file and Response itself, but also you need
to know which operation this response belongs to (in terms of OpenAPI).
Example:
$yamlFile = "api.yaml"; $operation = new \OpenAPIValidation\PSR7\OperationAddress('/password/gen', 'get') $validator = new \OpenAPIValidation\PSR7\ResponseValidator( $operation, \cebe\openapi\Reader::readFromYamlFile($yamlFile) ); $validator->validate($request);
Request Message
\Psr\Http\Message\RequestInterface
validation is not implemented.
PSR-15 Middleware
PSR-15 middleware can be used like this:
$middleware = \OpenAPIValidation\PSR15\ValidationMiddleware::fromYamlSpec("api.yaml"); # or $middleware = \OpenAPIValidation\PSR15\ValidationMiddleware::fromJsonSpec("api.yaml");
SlimFramework middleware
Slim framework uses slightly different middleware interface, so here is an adapter which you can use like this:
$psr15Middleware = \OpenAPIValidation\PSR15\ValidationMiddleware::fromYamlSpec ("api.yaml"); $slimMiddleware = new \OpenAPIValidation\PSR15\SlimAdapter($psr15Middleware); /** @var \Slim\App $app */ $app->add($slimMiddleware);
Standalone OpenAPI Validator
The package contains a standalone validator which can validate any data against an OpenAPI schema like this:
$spec = <<<SPEC schema: type: string enum: - a - b SPEC; $data = "c"; $spec = cebe\openapi\Reader::readFromYaml($spec); $schema = new cebe\openapi\spec\Schema($spec->schema); try { (new OpenAPIValidation\Schema\Validator($schema, $data))->validate(); } catch(\OpenAPIValidation\Schema\Exception\ValidationKeywordFailed $e) { // you can evaluate failure details // $e->keyword() == "enum" // $e->data() == "c" // $e->dataBreadCrumb()->buildChain() -- only for nested data }
Custom Type Formats
As you know, OpenAPI allows you to add formats to types:
schema: type: string format: binary
This package contains a bunch of built-in format validators:
string
type:byte
date
date-time
email
hostname
ipv4
ipv6
uri
uuid
(uuid4)
number
typefloat
double
You can also add your own formats. Like this:
# A format validator can be a callable # failed validation should throw an exception $customFormat = new class() { function __invoke($value): void { if ($value != "good value") { throw FormatMismatch::fromFormat('custom', $value); } } }; # Register your callable like this before validating tyour data \OpenAPIValidation\Schema\TypeFormats\FormatsContainer::registerFormat('string', 'unexpected', $unexpectedFormat);
Exceptions
The package throws a list of various exceptions which you can catch and handle. There are some of them:
- Schema related:
\OpenAPIValidation\Schema\Exception\ValidationKeywordFailed
- data does not match given keyword's rule. For exampletype:string
won't match integer12
.\OpenAPIValidation\Schema\Exception\FormatMismatch
- data mismatched a given type format. For exampletype: string, format: email
won't matchnot-email
.
- PSR7 Messages related:
\OpenAPIValidation\PSR7\Exception\NoContentType
- Response contains no Content-Type header. General HTTP errors.\OpenAPIValidation\PSR7\Exception\NoPath
- path is not found in the spec\OpenAPIValidation\PSR7\Exception\NoOperation
- operation os not found in the path\OpenAPIValidation\PSR7\Exception\NoResponseCode
- response code not found under the operation in the spec- Request related:
\OpenAPIValidation\PSR7\Exception \MultipleOperationsMismatchForRequest
- request matched multiple operations in the spec, but validation failed for all of them.\OpenAPIValidation\PSR7\Exception\MissedRequestCookie
- Request does not contain expected cookie\OpenAPIValidation\PSR7\Exception\MissedRequestHeader
- Request dons not contain expected header\OpenAPIValidation\PSR7\Exception\MissedRequestQueryArgument
- Request does not have expected query argument\OpenAPIValidation\PSR7\Exception\RequestBodyMismatch
- request's body does not match the specification schema\OpenAPIValidation\PSR7\Exception\RequestCookiesMismatch
- request's cookie does not match the specification schema\OpenAPIValidation\PSR7\Exception\RequestHeadersMismatch
- request's headers do not match spec schema\OpenAPIValidation\PSR7\Exception\RequestPathParameterMismatch
- request's path does not match spec's path template\OpenAPIValidation\PSR7\Exception\RequestQueryArgumentMismatch
- request's query arguments does not match the spec schema\OpenAPIValidation\PSR7\Exception\UnexpectedRequestContentType
- request's body content type is unexpected\OpenAPIValidation\PSR7\Exception\UnexpectedRequestHeader
- request carries unexpected header
- Response related:
\OpenAPIValidation\PSR7\Exception\MissedResponseHeader
- response does not have a header\OpenAPIValidation\PSR7\Exception\ResponseBodyMismatch
- response body does not match a schema\OpenAPIValidation\PSR7\Exception\ResponseHeadersMismatch
- response headers do not match the spec\OpenAPIValidation\PSR7\Exception\UnexpectedResponseHeader
- response contains header not mentioned in the spec\OpenAPIValidation\PSR7\Exception\UnexpectedResponseContentType
- response contains unexpected content-type
Testing
You can run the tests with:
vendor/bin/phpunit
Credits
People:
- Dmitry Lezhnev
- A big thank you to Henrik Karlström who kind of inspired me to work on this package.
Resources:
- Icons made by Freepik, licensed by CC 3.0 BY
- cebe/php-openapi package for Reading OpenAPI files
- slim3-psr15 package for Slim middleware adapter
License
The MIT License (MIT). Please see License.md
file for more information.
TODO
- support securitySchemes (top priority)
- parameters serialization
- Does anyone use this serialization? It looks very... unpractical.
- add validation for Request class.
- Usually for serverside testing purposes ServerRequest is what we need. But, Request should be quite easy to add.
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK