Skip to content

Commit

Permalink
feat(web-validation): replace deprecated SchemaParser with new Schema…
Browse files Browse the repository at this point in the history
…Repository

Signed-off-by: Pascal Krause <[email protected]>
  • Loading branch information
pk-work committed Jul 14, 2023
1 parent d790e40 commit 8b15f85
Show file tree
Hide file tree
Showing 28 changed files with 639 additions and 427 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
import io.vertx.ext.web.handler.HttpException;
import io.vertx.ext.web.validation.ValidationHandler;
import io.vertx.ext.web.validation.builder.ValidationHandlerBuilder;
import io.vertx.json.schema.SchemaParser;
import io.vertx.json.schema.SchemaRepository;
import io.vertx.serviceproxy.ServiceBinder;

import static io.vertx.ext.web.validation.builder.Bodies.json;
Expand All @@ -29,7 +29,8 @@
@Source
public class ApiCodegenExamples {

public void mountHandler(EventBus eventBus, Router router, ValidationHandler validationHandler) {
public void mountHandler(EventBus eventBus, Router router,
ValidationHandler validationHandler) {
router
.get("/hello")
.handler(validationHandler)
Expand All @@ -39,33 +40,38 @@ public void mountHandler(EventBus eventBus, Router router, ValidationHandler val
);
}

public void mountHandlerWithTimeout(EventBus eventBus, Router router, ValidationHandler validationHandler) {
public void mountHandlerWithTimeout(EventBus eventBus, Router router,
ValidationHandler validationHandler) {
router
.get("/hello")
.handler(validationHandler)
.handler(
RouteToEBServiceHandler
.build(eventBus, "greeters.myapplication", "hello", new DeliveryOptions().setSendTimeout(1000))
.build(eventBus, "greeters.myapplication", "hello",
new DeliveryOptions().setSendTimeout(1000))
);
}

public void serviceMountExample(EventBus eventBus, Router router, SchemaParser schemaParser) {
public void serviceMountExample(EventBus eventBus, Router router,
SchemaRepository repository) {
router.get("/api/transactions")
.handler(
ValidationHandlerBuilder.create(schemaParser)
ValidationHandlerBuilder.create(repository)
.queryParameter(optionalParam("from", stringSchema()))
.queryParameter(optionalParam("to", stringSchema()))
.build()
).handler(
RouteToEBServiceHandler.build(eventBus, "transactions.myapplication", "getTransactionsList")
RouteToEBServiceHandler.build(eventBus, "transactions.myapplication",
"getTransactionsList")
);
router.post("/api/transactions")
.handler(
ValidationHandlerBuilder.create(schemaParser)
ValidationHandlerBuilder.create(repository)
.body(json(objectSchema()))
.build()
).handler(
RouteToEBServiceHandler.build(eventBus, "transactions.myapplication", "putTransaction")
RouteToEBServiceHandler.build(eventBus, "transactions.myapplication",
"putTransaction")
);
}

Expand All @@ -80,7 +86,9 @@ public void serviceMount(Vertx vertx) {
.register(TransactionService.class, transactionService);
}

public void implGetTransactionsListSuccess(String from, String to, ServiceRequest context, Handler<AsyncResult<ServiceResponse>> resultHandler) {
public void implGetTransactionsListSuccess(String from, String to,
ServiceRequest context,
Handler<AsyncResult<ServiceResponse>> resultHandler) {
// Your business logic
resultHandler.handle(
Future.succeededFuture(
Expand All @@ -89,7 +97,9 @@ public void implGetTransactionsListSuccess(String from, String to, ServiceReques
);
}

public void implGetTransactionsListFailure(String from, String to, ServiceRequest context, Handler<AsyncResult<ServiceResponse>> resultHandler) {
public void implGetTransactionsListFailure(String from, String to,
ServiceRequest context,
Handler<AsyncResult<ServiceResponse>> resultHandler) {
// Return a failed result
resultHandler.handle(
Future.failedFuture(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,18 @@

import static io.vertx.ext.web.validation.builder.Bodies.json;
import static io.vertx.ext.web.validation.builder.Parameters.param;
import static io.vertx.ext.web.validation.testutils.TestRequest.*;
import static io.vertx.json.schema.draft7.dsl.Schemas.*;
import static io.vertx.ext.web.validation.testutils.TestRequest.bodyResponse;
import static io.vertx.ext.web.validation.testutils.TestRequest.emptyResponse;
import static io.vertx.ext.web.validation.testutils.TestRequest.jsonBodyResponse;
import static io.vertx.ext.web.validation.testutils.TestRequest.statusCode;
import static io.vertx.ext.web.validation.testutils.TestRequest.statusMessage;
import static io.vertx.ext.web.validation.testutils.TestRequest.testRequest;
import static io.vertx.json.schema.draft7.dsl.Schemas.anyOf;
import static io.vertx.json.schema.draft7.dsl.Schemas.arraySchema;
import static io.vertx.json.schema.draft7.dsl.Schemas.intSchema;
import static io.vertx.json.schema.draft7.dsl.Schemas.objectSchema;
import static io.vertx.json.schema.draft7.dsl.Schemas.ref;
import static io.vertx.json.schema.draft7.dsl.Schemas.stringSchema;

/**
* @author Francesco Guardiani @slinkydeveloper
Expand All @@ -52,7 +62,7 @@ public void serviceProxyTypedTest(Vertx vertx, VertxTestContext testContext) {
.post("/testE/:id")
.handler(BodyHandler.create())
.handler(
ValidationHandler.builder(parser)
ValidationHandler.builder(schemaRepo)
.pathParameter(param("id", intSchema()))
.body(json(objectSchema().property("value", intSchema())))
.build()
Expand All @@ -64,7 +74,7 @@ public void serviceProxyTypedTest(Vertx vertx, VertxTestContext testContext) {
.post("/testF/:id")
.handler(BodyHandler.create())
.handler(
ValidationHandler.builder(parser)
ValidationHandler.builder(schemaRepo)
.pathParameter(param("id", intSchema()))
.body(json(
anyOf(
Expand Down Expand Up @@ -106,7 +116,7 @@ public void serviceProxyDataObjectTest(Vertx vertx, VertxTestContext testContext
.post("/test")
.handler(BodyHandler.create())
.handler(
ValidationHandler.builder(parser)
ValidationHandler.builder(schemaRepo)
.body(json(ref(JsonPointer.fromURI(URI.create("filter.json")))))
.build()
).handler(
Expand Down Expand Up @@ -135,7 +145,7 @@ public void emptyOperationResultTest(Vertx vertx, VertxTestContext testContext)
router
.get("/test")
.handler(
ValidationHandler.builder(parser).build()
ValidationHandler.builder(schemaRepo).build()
).handler(
RouteToEBServiceHandler.build(vertx.eventBus(), "someAddress", "testEmptyServiceResponse")
);
Expand All @@ -157,7 +167,7 @@ public void authorizedUserTest(Vertx vertx, VertxTestContext testContext) {
router
.get("/test")
.handler(
ValidationHandler.builder(parser).build()
ValidationHandler.builder(schemaRepo).build()
).handler(rc -> {
rc.setUser(User.fromName("slinkydeveloper")); // Put user mock into context
rc.next();
Expand All @@ -183,7 +193,7 @@ public void extraPayloadTest(Vertx vertx, VertxTestContext testContext) {
router
.get("/test")
.handler(
ValidationHandler.builder(parser).build()
ValidationHandler.builder(schemaRepo).build()
).handler(
RouteToEBServiceHandler
.build(vertx.eventBus(), "someAddress", "extraPayload")
Expand All @@ -210,7 +220,7 @@ public void serviceProxyManualFailureTest(Vertx vertx, VertxTestContext testCont
.post("/testFailure")
.handler(BodyHandler.create())
.handler(
ValidationHandler.builder(parser)
ValidationHandler.builder(schemaRepo)
.body(json(
objectSchema()
.requiredProperty("hello", stringSchema())
Expand All @@ -227,7 +237,7 @@ public void serviceProxyManualFailureTest(Vertx vertx, VertxTestContext testCont
.post("/testException")
.handler(BodyHandler.create())
.handler(
ValidationHandler.builder(parser)
ValidationHandler.builder(schemaRepo)
.body(json(
objectSchema()
.requiredProperty("hello", stringSchema())
Expand Down Expand Up @@ -262,14 +272,14 @@ public void binaryDataTest(Vertx vertx, VertxTestContext testContext) {
.get("/test")
.handler(BodyHandler.create())
.handler(
ValidationHandler.builder(parser).build()
ValidationHandler.builder(schemaRepo).build()
).handler(
RouteToEBServiceHandler.build(vertx.eventBus(), "someAddress", "binaryTest")
);

testRequest(client, HttpMethod.GET, "/test")
.expect(statusCode(200), statusMessage("OK"))
.expect(bodyResponse(Buffer.buffer(new byte[] {(byte) 0xb0}), "application/octet-stream"))
.expect(bodyResponse(Buffer.buffer(new byte[]{(byte) 0xb0}), "application/octet-stream"))
.send(testContext, checkpoint);
}

Expand All @@ -284,7 +294,7 @@ public void authorizationPropagationTest(Vertx vertx, VertxTestContext testConte
router
.get("/test")
.handler(
ValidationHandler.builder(parser).build()
ValidationHandler.builder(schemaRepo).build()
).handler(rc -> {
// patch the request to include authorization header
rc.request().headers().add(HttpHeaders.AUTHORIZATION, "Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,10 @@
import org.junit.jupiter.api.extension.ExtendWith;

import static io.vertx.ext.web.validation.builder.Parameters.param;
import static io.vertx.ext.web.validation.testutils.TestRequest.*;
import static io.vertx.ext.web.validation.testutils.TestRequest.jsonBodyResponse;
import static io.vertx.ext.web.validation.testutils.TestRequest.statusCode;
import static io.vertx.ext.web.validation.testutils.TestRequest.statusMessage;
import static io.vertx.ext.web.validation.testutils.TestRequest.testRequest;
import static io.vertx.json.schema.draft7.dsl.Schemas.intSchema;

@SuppressWarnings("unchecked")
Expand All @@ -42,7 +45,7 @@ public void serviceProxyTypedTestWithRequestParameter(final Vertx vertx, final V
router
.post("/testFutureWithRequestParameter/:param")
.handler(BodyHandler.create())
.handler(ValidationHandler.builder(parser).pathParameter(param("param", intSchema())).build())
.handler(ValidationHandler.builder(schemaRepo).pathParameter(param("param", intSchema())).build())
.handler(
RouteToEBServiceHandler.build(vertx.eventBus(), "someAddress", "testFutureWithRequestParameter"));

Expand All @@ -63,7 +66,7 @@ public void serviceProxyTypedTestWithIntParameter(final Vertx vertx, final Vertx
router
.post("/testFutureWithIntParameter/:param")
.handler(BodyHandler.create())
.handler(ValidationHandler.builder(parser).pathParameter(param("param", intSchema())).build())
.handler(ValidationHandler.builder(schemaRepo).pathParameter(param("param", intSchema())).build())
.handler(
RouteToEBServiceHandler.build(vertx.eventBus(), "someAddress", "testFutureWithIntParameter"));

Expand All @@ -84,7 +87,7 @@ public void serviceProxyTypedTest(final Vertx vertx, final VertxTestContext test
router
.post("/testFuture")
.handler(BodyHandler.create())
.handler(ValidationHandler.builder(parser).build())
.handler(ValidationHandler.builder(schemaRepo).build())
.handler(
RouteToEBServiceHandler.build(vertx.eventBus(), "someAddress", "testFuture"));

Expand Down
19 changes: 8 additions & 11 deletions vertx-web-validation/src/main/asciidoc/index.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -57,22 +57,21 @@ Vert.x Web Validation provides an easy to use API to build an handler that perfo
== Creating the `ValidationHandler`

This module provides an easy to use builder API to create your {@link io.vertx.ext.web.validation.ValidationHandler}, the {@link io.vertx.core.Handler} that performs the parsing and validation of the request.
To create this builder use {@link io.vertx.ext.web.validation.builder.ValidationHandlerBuilder#create(SchemaParser)}.
The provided {@link io.vertx.json.schema.SchemaParser} will be used to parse all schemas created with https://vertx.io/docs/vertx-json-schema/$lang/[Vert.x Json Schema DSL]
To create this builder use {@link io.vertx.ext.web.validation.builder.ValidationHandlerBuilder#create(SchemaRepository)}.

=== Defining parameters

You can define parameters located in four different locations of your request: query, cookie, header, path.

Every parameter is represented by a {@link io.vertx.ext.web.validation.impl.parameter.ParameterProcessor},
that you can easily create with methods provided in {@link io.vertx.ext.web.validation.builder.Parameters}:
Every parameter is represented by a {@link io.vertx.ext.web.validation.impl.parameter.ParameterProcessor}, that you can easily create with methods provided in {@link io.vertx.ext.web.validation.builder.Parameters}:

[source,$lang]
----
{@link examples.WebValidationExamples#parameters}
----

Note that all these methods requires a schema that validator can use to perform the validation. The schema is also used to infer the correct parser
Note that all these methods requires a schema that validator can use to perform the validation.
The schema is also used to infer the correct parser

While header and path parameters allows only simple parameters, query and cookie allows complex parameters like exploded and deep object:

Expand All @@ -85,8 +84,7 @@ For more info on all available parameters, look at {@link io.vertx.ext.web.valid

=== Defining request bodies

Every body type is represented by a {@link io.vertx.ext.web.validation.impl.parameter.ParameterProcessor}
and matches with request body using `Content-type` header.
Every body type is represented by a {@link io.vertx.ext.web.validation.impl.parameter.ParameterProcessor} and matches with request body using `Content-type` header.
You can define one or multiple bodies that the `ValidationHandler` should manage.
If no matching body processor is found, the validation **won't** fail unless you specified the body required predicate explained below

Expand All @@ -98,8 +96,8 @@ You can easily create these processor with methods provided in {@link io.vertx.e
----

In this example the `ValidationHandler` will be able to manage two different body types that consistently parse and validate.
In particular the form body will be converted to a json object. When you retrieve the parsed result, you don't need to care
if the request body was a form or a json
In particular the form body will be converted to a json object.
When you retrieve the parsed result, you don't need to care if the request body was a form or a json

For more info on all available body processors, look at {@link io.vertx.ext.web.validation.builder.Bodies} documentation.

Expand Down Expand Up @@ -133,8 +131,7 @@ The `ValidationHandler` will place the parsed values into {@link io.vertx.ext.we

== Manage the failures

Every time a `ValidationHandler` encounters both a parsing or a validation failure, it fails the `RoutingContext` with 400 status code and
an instance of a subclass of {@link io.vertx.ext.web.validation.BadRequestException} as cause.
Every time a `ValidationHandler` encounters both a parsing or a validation failure, it fails the `RoutingContext` with 400 status code and an instance of a subclass of {@link io.vertx.ext.web.validation.BadRequestException} as cause.
To learn how to manage failures, look at https://vertx.io/docs/vertx-web/java/#_error_handling[Vert.x Web doc] and {@link io.vertx.ext.web.Router#errorHandler(int,Handler)} method.

The possible subclasses of {@link io.vertx.ext.web.validation.BadRequestException} are:
Expand Down
Loading

0 comments on commit 8b15f85

Please sign in to comment.