# Vert.x OpenAPI Router

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.CR1</version>
    </dependency>

- Gradle (in your `build.gradle` file):

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

## 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");
          });
      });