Vert.x Web 验证

Vert.x Web 验证帮助您解析和验证传入请求的参数和主体。

您可以

  • 解析并验证请求参数,包括序列化和扁平化的参数

  • 解析并验证请求主体,包括 JSON 和表单

  • 配置请求谓词

  • 在同一路由中允许不同的主体,并对其进行一致的解析和验证

  • 定义自定义解析和验证规则

  • 管理解析和验证失败

它使用 Vert.x JSON Schema 来定义请求参数/主体的模式。

使用 Vert.x Web 验证

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

  • Maven(在您的 pom.xml 中)

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

dependencies {
  compile 'io.vertx:vertx-web-validation:5.0.1'
}

不使用 Vert.x Web 验证

当您收到 HTTP 请求时,通常需要对请求的参数和主体进行解析和验证

router
  .get("/user")
  .handler(routingContext -> {
    // Retrieve aParam
    String aParamUnparsed = routingContext.queryParam("aParam").get(0);
    if (aParamUnparsed == null) {
      routingContext.fail(400);
      return;
    }
    // Parse aParam
    int aParam;
    try {
      aParam = Integer.parseInt(aParamUnparsed);
    } catch (NumberFormatException e) {
      routingContext.fail(400, e);
      return;
    }
    // Check if aParam is maximum 100
    if (aParam > 100) {
      routingContext.fail(400);
      return;
    }

    // aParam is ready, now we can focus on
    // Business logic to process the request
  });

Vert.x Web 验证提供了一个易于使用的 API,用于构建一个执行请求解析和验证的处理程序

router
  .get("/user")
  .handler(
    ValidationHandlerBuilder
      .create(schemaRepository)
      .queryParameter(param(
        "aParam",
        intSchema().with(maximum(100))
      ))
      .build()
  )
  .handler(routingContext -> {
    RequestParameters parameters =
      routingContext.get(ValidationHandler.REQUEST_CONTEXT_KEY);
    int aParam = parameters.queryParameter("aParam").getInteger();
    // Business logic to process the request
  });

创建 ValidationHandler

此模块提供了一个易于使用的构建器 API 来创建您的 ValidationHandler,即执行请求解析和验证的 Handler。要创建此构建器,请使用 ValidationHandlerBuilder.create

定义参数

您可以定义位于请求中四个不同位置的参数:查询、Cookie、请求头、路径。

每个参数都由一个 ParameterProcessor 表示,您可以使用 Parameters 中提供的方法轻松创建它。

ValidationHandlerBuilder
  .create(schemaRepository)
  .pathParameter(Parameters.param("myPathParam", stringSchema()))
  .queryParameter(Parameters.optionalParam("myQueryParam", intSchema()));

定义自定义错误消息

错误消息可以自定义

请注意,所有这些方法都需要一个验证器可以用于执行验证的模式。该模式也用于推断正确的解析器

虽然请求头和路径参数只允许简单参数,但查询和 Cookie 允许复杂参数,如扁平化和深层对象

ValidationHandlerBuilder
  .create(schemaRepository)
  .queryParameter(Parameters.explodedParam(
    "myArray",
    arraySchema().items(stringSchema())
  ))  // Accepts myArray=item1&myArray=item2
  .queryParameter(Parameters.deepObjectParam(
    "myDeepObject",
    objectSchema()
      .property("name", stringSchema())
  )); // Accepts myDeepObject[name]=francesco

有关所有可用参数的更多信息,请参阅 Parameters 文档。

定义请求主体

每种主体类型都由一个 ParameterProcessor 表示,并使用 Content-type 请求头与请求主体匹配。您可以定义一个或多个 ValidationHandler 应该管理的主体。如果没有找到匹配的主体处理器,验证不会失败,除非您指定了下面解释的主体必需谓词

您可以使用 Bodies 中提供的方法轻松创建这些处理器

ObjectSchemaBuilder bodySchemaBuilder = objectSchema()
  .property("username", stringSchema())
  .property("password", stringSchema());
ValidationHandlerBuilder
  .create(schemaRepository)
  .body(Bodies.json(bodySchemaBuilder))
  .body(Bodies.formUrlEncoded(bodySchemaBuilder));

在此示例中,ValidationHandler 将能够管理两种不同的主体类型,它们会进行一致的解析和验证。特别是表单主体将被转换为 JSON 对象。当您检索解析结果时,无需关心请求主体是表单还是 JSON

有关所有可用主体处理器的更多信息,请参阅 Bodies 文档。

定义请求谓词

您可以在 ValidationHandler 中使用 RequestPredicate 定义请求谓词。例如,定义一个“请求主体必需”谓词

ValidationHandlerBuilder
  .create(schemaRepository)
  .predicate(RequestPredicate.BODY_REQUIRED);

构建 ValidationHandler

配置完所有参数、主体和请求谓词后,您可以构建 ValidationHandler

router
  .get("/user")
  .handler(
    ValidationHandlerBuilder
      .create(schemaRepository)
      .build()
  );

使用已解析的参数和主体

ValidationHandler 会将解析后的值放入 RoutingContext

router
  .get("/user")
  .handler(
    ValidationHandlerBuilder
      .create(schemaRepository)
      .queryParameter(Parameters.explodedParam(
        "myArray",
        arraySchema().items(stringSchema())
      ))
      .body(Bodies.json(objectBodySchemaBuilder))
      .body(Bodies.formUrlEncoded(objectBodySchemaBuilder))
      .build()
  ).handler(routingContext -> {
    RequestParameters parameters =
      routingContext.get(ValidationHandler.REQUEST_CONTEXT_KEY);
    JsonArray myArray = parameters.queryParameter("myArray").getJsonArray();
    JsonObject body = parameters.body().getJsonObject();
  });

管理失败

每当 ValidationHandler 遇到解析或验证失败时,它都会以 400 状态码和 BadRequestException 子类实例作为原因使 RoutingContext 失败。要了解如何管理失败,请参阅 Vert.x Web 文档errorHandler 方法。

BadRequestException 可能的子类有

例如

router.errorHandler(400, routingContext -> {
  if (routingContext.failure() instanceof BadRequestException) {
    if (routingContext.failure() instanceof ParameterProcessorException) {
      // Something went wrong while parsing/validating a parameter
    } else if (routingContext.failure() instanceof BodyProcessorException) {
      // Something went wrong while parsing/validating the body
    } else if (routingContext.failure() instanceof RequestPredicateException) {
      // A request predicate is unsatisfied
    }
  }
});

BadRequestException 还提供了一个便捷的方法 toJson,可将异常转换为 JSON

请注意,ValidationHandler 被设计为快速失败,因此一旦遇到错误,ValidationHandler 将立即使 RoutingContext 失败