Vert.x OpenAPI

预览

Vert.x OpenAPI 扩展了 Vert.x,以支持 3.0 和 3.1 版本的 OpenAPI 3

Vert.x OpenAPI 可以

  • 解析并验证您的 OpenAPI 契约。

  • 根据您的 OpenAPI 契约解析并验证传入请求。

  • 根据您的 OpenAPI 契约解析并验证传出响应。

使用 Vert.x OpenAPI

要使用 Vert.x OpenAPI,请将以下依赖项添加到构建描述符的 dependencies 部分

  • Maven(在您的 pom.xml 中)

<dependency>
  <groupId>io.vertx</groupId>
  <artifactId>vertx-openapi</artifactId>
  <version>5.0.1</version>
</dependency>
  • Gradle(在您的 build.gradle 文件中)

dependencies {
  compile 'io.vertx:vertx-openapi:5.0.1'
}

OpenAPIContract

使用 Vert.x OpenAPI 时,您总是从您的契约创建一个 OpenAPIContract 实例开始。

String pathToContract = ".../.../myContract.json"; // json or yaml
Future<OpenAPIContract> contract = OpenAPIContract.from(vertx, pathToContract);
出于安全原因,此库不会从您的契约下载外部引用。如果您的契约需要外部资源,则必须提前下载并提供给 OpenAPIContract

以下示例展示了 OpenAPI 示例契约中的一个片段,其中包含对外部资源的引用以及如何创建 OpenAPIContract 实例。

paths:
  /pets:
    get:
      operationId: listPets
      parameters:
        - name: query
          schema:
            $ref: 'https://example.com/pet-components#/components/schemas/Query'
String pathToContract = ".../.../myContract.json"; // json or yaml
String pathToComponents = ".../.../myComponents.json"; // json or yaml
Map<String, String> additionalContractFiles = new HashMap<>();
additionalContractFiles.put("https://example.com/pet-components",
  pathToComponents);

Future<OpenAPIContract> contract =
  OpenAPIContract.from(vertx, pathToContract, additionalContractFiles);
在实例化 OpenAPIContract 期间,契约会得到验证。如果您的契约与 OpenAPI 规范不匹配或使用了尚不支持的功能,则会抛出错误。

Path, Operation, Parameter

OpenAPIContract 接口提供了导航到 OpenAPI 契约的 PathOperationParameter 对象的方法。

OpenAPIContract contract = getContract();

for (Path path : contract.getPaths()) {
  for (Parameter pathParameter : path.getParameters()) {
    // example methods of a OpenAPI parameter object
    pathParameter.isRequired();
    pathParameter.getSchema();
  }
  for (Operation operation : path.getOperations()) {
    // example methods of a OpenAPI operation object
    operation.getOperationId();
    operation.getRequestBody();
    operation.getParameters();
  }
}

验证

Vert.x OpenAPI 检查内容是否语法正确以及是否与模式相符。如果未定义模式或内容为二进制,则不执行模式验证。目前,仅支持以下媒体类型:

  • application/json

  • application/json+hal

  • application/octet-stream

  • multipart/form-data

未来计划支持更多媒体类型。同时计划支持 ContentAnalyser 的自定义实现,以便可以验证任何媒体类型。

请求验证

RequestValidator 提供了多个 validate 方法来验证传入请求。

OpenAPIContract contract = getContract();
RequestValidator validator = RequestValidator.create(vertx, contract);

vertx.createHttpServer().requestHandler(httpServerRequest -> {
  // Operation id must be determined for every request which is inefficient
  validator.validate(httpServerRequest).onSuccess(validatedRequest -> {
    validatedRequest.getBody(); // returns the body
    validatedRequest.getHeaders(); // returns the header
    // ..
    // ..
  });

  // Operation id will be passed to save effort for determining
  validator.validate(httpServerRequest, "yourOperationId")
    .onSuccess(validatedRequest -> {
      // do something
    });
}).listen(0);

RequestValidator 还提供了消耗 ValidatableRequestvalidate 方法签名。

OpenAPIContract contract = getContract();
RequestValidator validator = RequestValidator.create(vertx, contract);

ValidatableRequest request = getValidatableRequest();
validator.validate(request, "yourOperationId").onSuccess(validatedRequest -> {
  validatedRequest.getBody(); // returns the body
  validatedRequest.getHeaders(); // returns the header
  // ..
  // ..
});
ValidatableRequest 中的参数必须以特定格式存储,具体取决于其样式、位置以及是否展开,否则 RequestValidator 无法验证该请求。所需格式必须RequestValidator 的 JavaDoc 中描述的完全一致。

响应验证

ResponseValidator 提供了 validate 方法来验证响应。ValidatableResponse 提供了多个 create 方法,以便轻松构建可验证的响应。

如果响应验证通过,返回的 ValidatedResponse 可以直接发送回客户端。

OpenAPIContract contract = getContract();
ResponseValidator validator = ResponseValidator.create(vertx, contract);

JsonObject cat = new JsonObject().put("name", "foo");
ValidatableResponse response =
  ValidatableResponse.create(200, cat.toBuffer(), APPLICATION_JSON.toString());

vertx.createHttpServer().requestHandler(httpServerRequest -> {
  validator.validate(response, "yourOperationId")
    .onSuccess(validatedResponse -> {
      validatedResponse.getBody(); // returns the body
      validatedResponse.getHeaders(); // returns the header
      // ..
      // ..
      // send back the validated response
      validatedResponse.send(httpServerRequest.response());
    });
});
ValidatableResponse 中的参数必须以特定格式存储,具体取决于其样式、位置以及是否展开,否则 ResponseValidator 无法验证该响应。所需格式必须ResponseValidator 的 JavaDoc 中描述的完全一致。

处理验证异常

如果请求或响应验证失败,将抛出 ValidatorException。验证失败可能是由于格式原因,例如参数格式不正确或缺少必需参数。然而,验证当然也可能因为内容与定义的模式不匹配而失败。在这种情况下,会抛出 SchemaValidationException。它是 ValidatorException 的子类,并提供对相关 OutputUnit 的访问,以便进一步分析错误。