<dependency>
<groupId>io.vertx</groupId>
<artifactId>vertx-web-openapi</artifactId>
<version>4.0.3</version>
</dependency>
Vert.x OpenAPI
Vert.x OpenAPI extends Vert.x Web to support OpenAPI 3, bringing to you a simple interface to build a Vert.x Web Router conforming your API contract.
Vert.x OpenAPI can:
-
Parse and validate the your OpenAPI 3 contract
-
Generate a router according to your spec, with correct path & methods
-
Provide request parsing and validation based on your contract using Vert.x Web Validation
-
Mount required security handlers
-
Path conversion between OpenAPI style and Vert.x style
-
Route requests to event bus using Vert.x Web API Service
Using Vert.x OpenAPI
To use Vert.x OpenAPI, add the following dependency to the dependencies section of your build descriptor:
-
Maven (in your
pom.xml
):
-
Gradle (in your
build.gradle
file):
dependencies {
compile 'io.vertx:vertx-web-openapi:4.0.3'
}
RouterBuilder
RouterBuilder
is the main element of this module: It provides the interface to mount request handlers and generates the final Router
To start using Vert.x Web OpenAPI, you must instantiate RouterBuilder
with your contract using RouterBuilder.create
For example to load a spec from the local filesystem:
RouterBuilder.create(vertx, "src/main/resources/petstore.yaml").onComplete(ar -> {
if (ar.succeeded()) {
// Spec loaded with success
RouterBuilder routerBuilder = ar.result();
} else {
// Something went wrong during router builder initialization
Throwable exception = ar.cause();
}
});
You can construct a router builder from a remote spec:
RouterBuilder.create(
vertx,
"https://raw.githubusercontent" +
".com/OAI/OpenAPI-Specification/master/examples/v3.0/petstore.yaml"
).onComplete(ar -> {
if (ar.succeeded()) {
// Spec loaded with success
RouterBuilder routerBuilder = ar.result();
} else {
// Something went wrong during router builder initialization
Throwable exception = ar.cause();
}
});
You can access a private remote spec configuring OpenAPILoaderOptions
:
OpenAPILoaderOptions loaderOptions = new OpenAPILoaderOptions()
.putAuthHeader("Authorization", "Bearer xx.yy.zz");
RouterBuilder.create(
vertx,
"https://raw.githubusercontent" +
".com/OAI/OpenAPI-Specification/master/examples/v3.0/petstore.yaml",
loaderOptions
).onComplete(ar -> {
if (ar.succeeded()) {
// Spec loaded with success
RouterBuilder routerBuilder = ar.result();
} else {
// Something went wrong during router builder initialization
Throwable exception = ar.cause();
}
});
You can modify different behaviours of the router builder with RouterBuilderOptions
:
routerBuilder.setOptions(new RouterBuilderOptions());
Access to operations
To access to an Operation defined in contract, use operation
. This method returns an Operation
instance that you can use to both access the model and assign handlers
To mount an handler to an operation use handler
, to mount a failure handler use failureHandler
You can add multiple handlers to same operation, without overwrite the existing ones.
For example:
routerBuilder
.operation("awesomeOperation")
.handler(routingContext -> {
RequestParameters params =
routingContext.get(ValidationHandler.REQUEST_CONTEXT_KEY);
RequestParameter body = params.body();
JsonObject jsonBody = body.getJsonObject();
// Do something with body
}).failureHandler(routingContext -> {
// Handle failure
});
You can’t access to contract operations without |
Vert.x OpenAPI mounts the correct ValidationHandler
for you, so you can access to request parameters and request body. Refer to Vert.x Web Validation documentation to learn how to get request parameters & request body and how to manage validation failures
Map AuthenticationHandler
to OpenAPI security schemes
You can map an AuthenticationHandler
to a security schema defined in the contract.
For example, given your contract has a security schema named security_scheme_name
:
routerBuilder.securityHandler("security_scheme_name", authenticationHandler);
You can mount AuthenticationHandler
included in Vert.x Web, for example:
routerBuilder.securityHandler("jwt_auth",
JWTAuthHandler.create(jwtAuthProvider));
When you generate the Router
the router builder will solve the security schemes required for an operation. It fails if there is a missing AuthenticationHandler
required by a configured operation.
For debugging/testing purpose you can disable this check with setRequireSecurityHandlers
Not Implemented Error
Router builder automatically mounts a default handler for operations without a specified handler. This default handler fails the routing context with 405 Method Not Allowed
/501 Not Implemented
error. You can enable/disable it with setMountNotImplementedHandler
and you can customize this error handling with errorHandler
Response Content Type Handler
Router builder automatically mounts a ResponseContentTypeHandler
handler when contract requires it. You can disable this feature with setMountResponseContentTypeHandler
Operation model
If you need to access to your operation model while handling the request, you can configure the router builder to push it inside the RoutingContext
with setOperationModelKey
:
options.setOperationModelKey("operationModel");
routerBuilder.setOptions(options);
// Add an handler that uses the operation model
routerBuilder
.operation("listPets")
.handler(
routingContext -> {
JsonObject operation = routingContext.get("operationModel");
routingContext
.response()
.setStatusCode(200)
.setStatusMessage("OK")
// Write the response with operation id "listPets"
.end(operation.getString("operationId"));
});
Body Handler
Router builder automatically mounts a BodyHandler
to manage request bodies. You can configure the instance of BodyHandler
(e.g. to change upload directory) with bodyHandler
.
multipart/form-data
validation
The validation handler separates file uploads and form attributes as explained:
-
If the parameter doesn’t have an encoding associated field:
-
If the parameter has
type: string
andformat: base64
orformat: binary
is a file upload with content-typeapplication/octet-stream
-
Otherwise is a form attribute
-
-
If the parameter has the encoding associated field is a file upload
The form attributes are parsed, converted in json and validated, while for file uploads the validation handler just checks the existence and the content type.
Custom global handlers
If you need to mount handlers that must be executed for each operation in your router before the operation specific handlers, you can use rootHandler
Router builder handlers mount order
Handlers are loaded by the router builder in this order:
-
Body handler
-
Custom global handlers
-
Configured `AuthenticationHandler`s
-
Generated
ValidationHandler
-
User handlers or "Not implemented" handler (if enabled)
Generate the router
When you are ready, generate the router and use it:
Router router = routerBuilder.createRouter();
HttpServer server =
vertx.createHttpServer(new HttpServerOptions().setPort(8080).setHost(
"localhost"));
server.requestHandler(router).listen();
This method can fail with a RouterBuilderException
.
If you need to mount all the router generated by router builder under the same parent path, you can use |