You are currently viewing the documentation for the unreleased version 5.0.0.CR2 of Vert.x. Visit the latest stable version of this page.

Vert.x OpenAPI Router

Preview

Vert.x OpenAPI Router is based on Vert.x OpenAPI and only provides the router functionality.

Vert.x OpenAPI Router can:

  • generate a router according to your OpenAPI contract, with correct paths & methods.

Using Vert.x OpenAPI Router

To use Vert.x OpenAPI Router, add the following dependency to the dependencies section of your build descriptor:

  • Maven (in your pom.xml):

<dependency>
  <groupId>io.vertx</groupId>
  <artifactId>vertx-web-openapi-router</artifactId>
  <version>5.0.0.CR2</version>
</dependency>
  • Gradle (in your build.gradle file):

dependencies {
  compile 'io.vertx:vertx-web-openapi-router:5.0.0.CR2'
}

RouterBuilder

With the RouterBuilder you can easily generate a Vert.x Web Router based on the passed OpenAPIContract.

OpenAPIContract contract = getContract();
RouterBuilder routerBuilder = RouterBuilder.create(vertx, contract);
Router router = routerBuilder.createRouter();

// In case that a BodyHandler was applied before, it is necessary to pass a RequestExtractor
RouterBuilder.create(vertx, contract, RequestExtractor.withBodyHandler());

The RouterBuilder provides methods to access the generated routes. These routes can then be customized by adding custom handlers or enable / disable the validation.

OpenAPIRoute getPetsRoute = routerBuilder.getRoute("getPets");

// Disables validation for this route.
getPetsRoute.setDoValidation(false);

for (OpenAPIRoute route : routerBuilder.getRoutes()) {
  // Access the operation object from the contract
  Operation operation = route.getOperation();

  // Add a custom handler
  route.addHandler(routingContext -> {
    // do something
  });

  // Add a failure handler
  route.addFailureHandler(routingContext -> {
    // do something
  });
}

After a successful validation of the incoming request, the validated parameters and request body are stored in the RoutingContext and can be accessed inside your custom handlers.

OpenAPIRoute putPetRoute = routerBuilder.getRoute("putPet");

putPetRoute.addHandler(routingContext -> {
  ValidatedRequest validatedRequest =
    routingContext.get(RouterBuilder.KEY_META_DATA_VALIDATED_REQUEST);

  validatedRequest.getBody(); // returns the body
  validatedRequest.getHeaders(); // returns the header
  // ..
  // ..
});

Define security handlers

Security is an important aspect of the OpenAPI specification. The security allows you to define security handlers.

Users are expected to call this method for each security scheme defined in the OpenAPI contract. Not doing so will result in a failure when generating the router. Also providing other handlers that the ones defined in the contract will result in a failure.

A security handler can be automatically configured for the cases of apiKey and http security schemes. For other cases, you need to provide a custom handler factory that receives as input the specified configuration from the OpenAPI contract.

For example:

RouterBuilder routerBuilder = RouterBuilder.create(vertx, contract);

// Add a security handler for "api_key" security scheme
// configuration will be automatically read from the contract and applied
// to the handler
routerBuilder
  .security("api_key")
  .apiKeyHandler(APIKeyHandler.create(provider));

// Add a security handler for "http" "bearer" security scheme
routerBuilder
  .security("http_bearer")
  .httpHandler(JWTAuthHandler.create(providerJWT));

Of course Oauth2/openIdConnect are also supported, given that these modes are more complex to configure, instead of providing a simple configuration object, you need to provide a factory that can creates the handler as you need. The factory will receive the configuration from the contract, or in case of openIdConnect the configuration discovery URL.

RouterBuilder routerBuilder = RouterBuilder.create(vertx, contract);

// Add a security handler for "oauth2" security scheme
routerBuilder
  .security("oauth2")
  .oauth2Handler("/callback", flowsConfig -> {
    // flowsConfig is a JsonObject with the configuration for the flows
    // you can use it to create the "providerOAuth2" instance
    return OAuth2AuthHandler.create(
      vertx,
      providerOAuth2,
      // there should a relation between this origin and the callback above
      "https://my-application-server.com/callback");
  });

Discovery may sound simpler and if you are working with a openId compliant server you can use the the openIdConnect security scheme.

RouterBuilder routerBuilder = RouterBuilder.create(vertx, contract);

// Add a security handler for "openIdConnect" security scheme
routerBuilder
  .security("openIdConnect")
  .openIdConnectHandler("/callback", discoveryUrl -> {
    return OpenIDConnectAuth.discover(
      vertx,
      new OAuth2Options()
        .setClientId("client-id")
        .setClientSecret("client-secret"))
      .map(openIdConnect -> {
        return OAuth2AuthHandler.create(
          vertx,
          openIdConnect,
          // there should a relation between this origin and the callback above
          "https://my-application-server.com/callback");
      });
  });