My GSoC 2017 - OpenAPI 3 Vert.x support
The support to OpenAPI 3 it’s located in maven package vertx-web-api-contract-openapi
, and most classes extends/subclass from interfaces/classes inside maven package vertx-web-api-contract-common
(the package designed to contain all API Specs standards common classes). Most important interfaces of vertx-web-api-contract-openapi
are:
- The
OpenAPI3ValidationHandler
class that fillsBaseValidationHandler
maps - The
OpenAPI3RouterFactory
, the interface that enable users create a router with your API spec
As I said in a previous blog post, OpenAPI 3 added a lot of new things, in particular about serialization styles and complex form bodies (url encoded and multipart). So when I started working on OpenAPI 3 requests validations, I had to add a lot of things to validation framework that I haven’t expected before.
The validation handler
OpenAPI3ValidationHandler
is an interface extension of HTTPOperationRequestValidationHandler
(located inside vertx-web-api-contract-common
), that is an interface extension of ValidationHandler
. This class contains all methods to elaborate the Operation
object (Java representation of OAS3 operation object) and the list of Parameter
objects (Java representation of OAS3 parameter object).
When constructed, it generates all ParameterValidationRule
and ParameterTypeValidator
it needs: in fact, It doesn’t elaborate the api spec nor work with api spec Java models during the validation. It does everything when It’s constructed, so It iterates through various parameters and It generates objects needed for validation.
If you read this class, It seems messy, because It's messy 😄. This is because of complexity of OAS 3, that forced me to write some little tricks to support all things (like for example to manage the `deepObject` serialization style).
To give a quick explanation of how this class elaborates parameters:
- It checks if it’s supported (parameters with
allowReserved: true
are not supported) - It checks if the parameter needs a workaround to get validation working and applies the specific workaround
- If none workaround is needed, it constructs the correct type validator
Behind the scenes all the validation work is done by validation framework
The router factory
The router factory is intended to give the most simple user interface to generate a router based on an API Spec. In fact, it provides this functionalities:
- Async loading of specification and its schema dependencies
- OpenAPI 3 compliant API specification validation (thanks to Kaizen-OpenApi-Parser)
- Load handlers and failure handlers with operationId
- Automatic 501 (Not implemented) response for operations with missing handlers (can be enabled/disabled with
mountOperationsWithoutHandlers(boolean)
) - Automatic
ValidationException
failure handler (can be enabled/disabled withenableValidationFailureHandler()
and manually configured withsetValidationFailureHandler()
) - Path’s regular expression generation (to support
matrix
andlabel
style unsupported natively from Vert.x) - Lazy methods: the generation of the
Router
is done only when you callgetRouter()
- Automatic mount of security validation handlers
Lazy methods
It’s usual to run into problems regards route declaration order. For example if you declare two routes in this order:
GET /hello/{parameter}
GET /hello/world
With actual Vert.x Router
implementation, /hello/world
handler will never called, unless you explicitly call RoutingContext#next()
inside /hello/{parameter}
handler (that causes Router
to run the next route matching the pattern). With lazy methods It’s guaranteed that routes will be loaded with order declared inside API specification.
I choose lazy methods also for code style reasons, It helps a lot to manage the code of router factory.
And the final result
With this tools, user can bring OpenAPI 3 power to its Vert.x server implementation as simple as:
1 | OpenAPI3RouterFactory.createRouterFactoryFromFile(this.vertx, "src/main/resources/petstore.yaml", ar -> { |
Next time I’m going to introduce you slush-vertx
, a new generator for Vert.x project. Stay tuned!