This is an automated email from the ASF dual-hosted git repository.
aldettinger pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel-quarkus.git
The following commit(s) were added to refs/heads/main by this push:
new 34bf4efd7d Complete vertx-http test coverage #4658 (#4708)
34bf4efd7d is described below
commit 34bf4efd7dbd3f2adb2265a20fb456849fc7ffef
Author: Alexandre Gallice <[email protected]>
AuthorDate: Wed Mar 29 14:01:48 2023 +0200
Complete vertx-http test coverage #4658 (#4708)
* vertx-http: complete test coverage #4658
* vertx-http: add test coverage for multipart form data #4658
* vertx-http: add test of custom vertxOptions
* vertx-http: add session management test
* vertx-http: add test coverage for buffer conversion with dynamic encoding
* vertx-http: complete allowJavaSerializedObject doc
---
.../pages/reference/extensions/vertx-http.adoc | 15 +++
.../runtime/src/main/doc/configuration.adoc | 8 ++
integration-tests/http/pom.xml | 4 +
.../quarkus/component/http/it/HttpResource.java | 107 +++++++++++++++++++++
.../camel/quarkus/component/http/it/HttpRoute.java | 3 +
.../quarkus/component/http/it/HttpService.java | 59 ++++++++++++
...e.java => VertxClientRelatedBeansProducer.java} | 36 +++----
.../http/src/main/resources/application.properties | 1 +
.../camel/quarkus/component/http/it/HttpTest.java | 67 +++++++++++++
9 files changed, 282 insertions(+), 18 deletions(-)
diff --git a/docs/modules/ROOT/pages/reference/extensions/vertx-http.adoc
b/docs/modules/ROOT/pages/reference/extensions/vertx-http.adoc
index 6ab4f34ed2..82dd75c911 100644
--- a/docs/modules/ROOT/pages/reference/extensions/vertx-http.adoc
+++ b/docs/modules/ROOT/pages/reference/extensions/vertx-http.adoc
@@ -55,3 +55,18 @@ You will also need to enable serialization for the exception
classes that you in
----
@RegisterForReflection(targets = { IllegalStateException.class,
MyCustomException.class }, serialization = true)
----
+
+[id="extensions-vertx-http-additional-camel-quarkus-configuration"]
+== Additional Camel Quarkus configuration
+
+[id="extensions-vertx-http-configuration-allowjavaserializedobject-option-in-native-mode"]
+== allowJavaSerializedObject option in native mode
+
+When using the `allowJavaSerializedObject` option in native mode, the support
of serialization might need to be enabled.
+Please, refer to the xref:user-guide/native-mode.adoc#serialization[native
mode user guide] for more information.
+
+[id="extensions-vertx-http-configuration-character-encodings"]
+=== Character encodings
+
+Check the xref:user-guide/native-mode.adoc#charsets[Character encodings
section] of the Native mode guide if the application is expected to send and
receive requests using non-default encodings.
+
diff --git a/extensions/vertx-http/runtime/src/main/doc/configuration.adoc
b/extensions/vertx-http/runtime/src/main/doc/configuration.adoc
new file mode 100644
index 0000000000..431ced5e7c
--- /dev/null
+++ b/extensions/vertx-http/runtime/src/main/doc/configuration.adoc
@@ -0,0 +1,8 @@
+== allowJavaSerializedObject option in native mode
+
+When using the `allowJavaSerializedObject` option in native mode, the support
of serialization might need to be enabled.
+Please, refer to the xref:user-guide/native-mode.adoc#serialization[native
mode user guide] for more information.
+
+=== Character encodings
+
+Check the xref:user-guide/native-mode.adoc#charsets[Character encodings
section] of the Native mode guide if the application is expected to send and
receive requests using non-default encodings.
diff --git a/integration-tests/http/pom.xml b/integration-tests/http/pom.xml
index ecf338fd83..ab2905b83b 100644
--- a/integration-tests/http/pom.xml
+++ b/integration-tests/http/pom.xml
@@ -99,6 +99,10 @@
<artifactId>quarkus-junit4-mock</artifactId>
<scope>test</scope>
</dependency>
+ <dependency>
+ <groupId>org.jboss.resteasy</groupId>
+ <artifactId>resteasy-multipart-provider</artifactId>
+ </dependency>
<!-- test dependencies - camel-quarkus -->
<dependency>
diff --git
a/integration-tests/http/src/main/java/org/apache/camel/quarkus/component/http/it/HttpResource.java
b/integration-tests/http/src/main/java/org/apache/camel/quarkus/component/http/it/HttpResource.java
index 92a8f5d35d..15acdc449c 100644
---
a/integration-tests/http/src/main/java/org/apache/camel/quarkus/component/http/it/HttpResource.java
+++
b/integration-tests/http/src/main/java/org/apache/camel/quarkus/component/http/it/HttpResource.java
@@ -22,6 +22,8 @@ import java.nio.charset.StandardCharsets;
import java.util.Base64;
import java.util.zip.GZIPInputStream;
+import io.vertx.core.buffer.Buffer;
+import io.vertx.ext.web.multipart.MultipartForm;
import jakarta.annotation.security.RolesAllowed;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject;
@@ -38,13 +40,19 @@ import jakarta.ws.rs.core.Response;
import org.apache.camel.ConsumerTemplate;
import org.apache.camel.Exchange;
import org.apache.camel.FluentProducerTemplate;
+import org.apache.camel.Message;
+import org.apache.camel.PropertyBindingException;
+import org.apache.camel.ResolveEndpointFailedException;
import org.apache.camel.RoutesBuilder;
import org.apache.camel.builder.EndpointConsumerBuilder;
import org.apache.camel.builder.EndpointProducerBuilder;
import org.apache.camel.builder.endpoint.EndpointRouteBuilder;
+import org.apache.camel.http.base.HttpOperationFailedException;
import org.apache.camel.util.IOHelper;
import org.eclipse.microprofile.config.ConfigProvider;
+import static
org.apache.camel.component.vertx.http.VertxHttpConstants.CONTENT_TYPE_FORM_URLENCODED;
+
@Path("/test/client")
@ApplicationScoped
public class HttpResource {
@@ -378,6 +386,105 @@ public class HttpResource {
return exchange.getException().getClass().getName();
}
+ @Path("/vertx-http/multipart-form-params")
+ @GET
+ @Produces(MediaType.TEXT_PLAIN)
+ public String vertxHttpMultipartFormParams(@QueryParam("test-port") int
port,
+ @QueryParam("organization") String organization,
+ @QueryParam("project") String project) {
+ return producerTemplate
+
.toF("vertx-http:http://localhost:%d/service/multipart-form-params", port)
+ .withBody("organization=" + organization + "&project=" +
project)
+ .withHeader(Exchange.CONTENT_TYPE,
CONTENT_TYPE_FORM_URLENCODED)
+ .request(String.class);
+ }
+
+ @Path("/vertx-http/multipart-form-data")
+ @GET
+ @Produces(MediaType.TEXT_PLAIN)
+ public String vertxHttpMultipartFormData(@QueryParam("test-port") int
port) {
+
+ MultipartForm form = MultipartForm.create();
+ form.binaryFileUpload("part-1", "test1.txt",
Buffer.buffer("part1=content1".getBytes(StandardCharsets.UTF_8)),
+ "text/plain");
+ form.binaryFileUpload("part-2", "test2.xml",
+ Buffer.buffer("<part2
value=\"content2\"/>".getBytes(StandardCharsets.UTF_8)), "text/xml");
+
+ return producerTemplate
+
.toF("vertx-http:http://localhost:%d/service/multipart-form-data", port)
+ .withBody(form)
+ .request(String.class);
+ }
+
+ @Path("/vertx-http/custom-vertx-options")
+ @GET
+ @Produces(MediaType.TEXT_PLAIN)
+ public String vertxHttpCustomVertxOptions(@QueryParam("test-port") int
port) {
+ try {
+ producerTemplate
+
.toF("vertx-http:http://localhost:%d/service/custom-vertx-options?vertxOptions=#myVertxOptions",
port)
+ .request();
+ return "NOT_EXPECTED: the custom vertxOptions should have
triggered a ResolveEndpointFailedException";
+ } catch (ResolveEndpointFailedException refex) {
+ Throwable firstLevelExceptionCause = refex.getCause();
+ if (firstLevelExceptionCause instanceof PropertyBindingException) {
+ if (firstLevelExceptionCause.getCause() instanceof
IllegalArgumentException) {
+ return "OK: the custom vertxOptions has triggered the
expected exception";
+ }
+ return "NOT_EXPECTED: the 2nd level exception cause should be
of type IllegalArgumentException";
+ } else {
+ return "NOT_EXPECTED: the 1st level exception cause should be
of type PropertyBindingException";
+ }
+ }
+ }
+
+ @Path("/vertx-http/session-management")
+ @GET
+ @Produces(MediaType.TEXT_PLAIN)
+ public String vertxHttpSessionManagement(@QueryParam("test-port") int
port) {
+ String vertxHttpBaseUri = "vertx-http:http://localhost:" + port +
"/service/session-management";
+ Exchange result = producerTemplate
+
.toF("%s/secure?sessionManagement=true&cookieStore=#myVertxCookieStore",
vertxHttpBaseUri)
+ .request(Exchange.class);
+
+ HttpOperationFailedException exception =
result.getException(HttpOperationFailedException.class);
+ if (exception.getStatusCode() != 403) {
+ return "NOT_EXPECTED: The first request in the session is expected
to return HTTP 403";
+ }
+
+ result = producerTemplate
+
.toF("%s/login?sessionManagement=true&cookieStore=#myVertxCookieStore",
vertxHttpBaseUri)
+ .withHeader("username", "my-username")
+ .withHeader("password", "my-password")
+ .request(Exchange.class);
+
+ Message msg = result.getMessage();
+ if (msg == null) {
+ return "NOT_EXPECTED: The second request in the session should
return a message";
+ } else {
+ String setCookieHeader = msg.getHeader("Set-Cookie", String.class);
+ if (setCookieHeader == null ||
!setCookieHeader.contains("sessionId=my-session-id-123")) {
+ return "NOT_EXPECTED: The message should have a Set-Cookie
String header containing \"sessionId=my-session-id-123\"";
+ }
+ }
+
+ return producerTemplate
+
.toF("%s/secure?sessionManagement=true&cookieStore=#myVertxCookieStore",
vertxHttpBaseUri)
+ .request(String.class);
+ }
+
+ @Path("/vertx-http/buffer-conversion-with-charset")
+ @GET
+ public byte[] vertxBufferConversionWithCharset(@QueryParam("string")
String string, @QueryParam("charset") String charset) {
+ Buffer buffer = producerTemplate
+ .to("direct:vertx-http-buffer-conversion-with-charset")
+ .withBody(string)
+ .withHeader(Exchange.CONTENT_TYPE, "text/plain;charset=" +
charset)
+ .request(Buffer.class);
+
+ return buffer.getBytes();
+ }
+
// *****************************
//
// Send dynamic tests
diff --git
a/integration-tests/http/src/main/java/org/apache/camel/quarkus/component/http/it/HttpRoute.java
b/integration-tests/http/src/main/java/org/apache/camel/quarkus/component/http/it/HttpRoute.java
index 4f4311d761..393857a7f6 100644
---
a/integration-tests/http/src/main/java/org/apache/camel/quarkus/component/http/it/HttpRoute.java
+++
b/integration-tests/http/src/main/java/org/apache/camel/quarkus/component/http/it/HttpRoute.java
@@ -19,6 +19,7 @@ package org.apache.camel.quarkus.component.http.it;
import java.io.InputStream;
import io.quarkus.runtime.annotations.RegisterForReflection;
+import io.vertx.core.buffer.Buffer;
import jakarta.inject.Named;
import org.apache.camel.Exchange;
import org.apache.camel.Processor;
@@ -76,6 +77,8 @@ public class HttpRoute extends RouteBuilder {
from("netty-http:http://0.0.0.0:{{camel.netty-http.test-port}}/test/server/myService")
.transform().constant("Hello from myService");
+ from("direct:vertx-http-buffer-conversion-with-charset")
+ .convertBodyTo(Buffer.class);
}
@Named
diff --git
a/integration-tests/http/src/main/java/org/apache/camel/quarkus/component/http/it/HttpService.java
b/integration-tests/http/src/main/java/org/apache/camel/quarkus/component/http/it/HttpService.java
index 54e1594690..ead9323b87 100644
---
a/integration-tests/http/src/main/java/org/apache/camel/quarkus/component/http/it/HttpService.java
+++
b/integration-tests/http/src/main/java/org/apache/camel/quarkus/component/http/it/HttpService.java
@@ -16,13 +16,21 @@
*/
package org.apache.camel.quarkus.component.http.it;
+import java.util.Map;
+
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.ws.rs.Consumes;
+import jakarta.ws.rs.CookieParam;
+import jakarta.ws.rs.ForbiddenException;
+import jakarta.ws.rs.FormParam;
import jakarta.ws.rs.GET;
+import jakarta.ws.rs.HeaderParam;
import jakarta.ws.rs.POST;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.core.MediaType;
+import jakarta.ws.rs.core.NewCookie;
+import jakarta.ws.rs.core.Response;
@Path("/service")
@ApplicationScoped
@@ -41,4 +49,55 @@ public class HttpService {
public String toUpper(String message) {
return message.toUpperCase();
}
+
+ @POST
+ @Path("/multipart-form-params")
+ @Consumes(MediaType.APPLICATION_FORM_URLENCODED)
+ @Produces(MediaType.TEXT_PLAIN)
+ public String multipartFormParams(@FormParam("organization") String
organization, @FormParam("project") String project) {
+ return String.format("multipartFormParams(%s, %s)", organization,
project);
+ }
+
+ @POST
+ @Path("/multipart-form-data")
+ @Consumes(MediaType.MULTIPART_FORM_DATA)
+ @Produces(MediaType.TEXT_PLAIN)
+ public String multipartFormData(Map<String, String> parts) {
+ if (parts.size() != 2 || !parts.keySet().contains("part-1") ||
!parts.keySet().contains("part-2")) {
+ throw new IllegalArgumentException(
+ "There should be exactly 2 parts named \"part-1\" and
\"parts-2\" in the multipart upload");
+ }
+ return String.format("multipartFormData(%s, %s)", parts.get("part-1"),
parts.get("part-2"));
+ }
+
+ @GET
+ @Path("/custom-vertx-options")
+ public void customVertxOptions() {
+ // We are not expected to pass here as the Vert.x HTTP client should
throw IllegalArgumentException
+ }
+
+ @GET
+ @Path("/session-management/secure")
+ @Produces(MediaType.TEXT_PLAIN)
+ public String getSecuredContent(@CookieParam("sessionId") String cookie) {
+ if ("my-session-id-123".equals(cookie)) {
+ return "Some secret content";
+ } else {
+ throw new ForbiddenException("A cookie with session id is needed
to access the secured content");
+ }
+ }
+
+ @GET
+ @Path("/session-management/login")
+ @Produces(MediaType.TEXT_PLAIN)
+ public Response login(@HeaderParam("username") String username,
@HeaderParam("password") String password) {
+ if ("my-username".equals(username) && "my-password".equals(password)) {
+ NewCookie cookie = new NewCookie.Builder("sessionId")
+ .value("my-session-id-123")
+ .build();
+ return Response.ok().cookie(cookie).build();
+ }
+ throw new ForbiddenException("Wrong username/password, no cookie will
be created");
+ }
+
}
diff --git
a/integration-tests/http/src/main/java/org/apache/camel/quarkus/component/http/it/HttpService.java
b/integration-tests/http/src/main/java/org/apache/camel/quarkus/component/http/it/VertxClientRelatedBeansProducer.java
similarity index 61%
copy from
integration-tests/http/src/main/java/org/apache/camel/quarkus/component/http/it/HttpService.java
copy to
integration-tests/http/src/main/java/org/apache/camel/quarkus/component/http/it/VertxClientRelatedBeansProducer.java
index 54e1594690..3f6949d0c2 100644
---
a/integration-tests/http/src/main/java/org/apache/camel/quarkus/component/http/it/HttpService.java
+++
b/integration-tests/http/src/main/java/org/apache/camel/quarkus/component/http/it/VertxClientRelatedBeansProducer.java
@@ -16,29 +16,29 @@
*/
package org.apache.camel.quarkus.component.http.it;
+import io.vertx.core.VertxOptions;
+import io.vertx.ext.web.client.spi.CookieStore;
import jakarta.enterprise.context.ApplicationScoped;
-import jakarta.ws.rs.Consumes;
-import jakarta.ws.rs.GET;
-import jakarta.ws.rs.POST;
-import jakarta.ws.rs.Path;
+import jakarta.inject.Named;
+import jakarta.inject.Singleton;
import jakarta.ws.rs.Produces;
-import jakarta.ws.rs.core.MediaType;
-@Path("/service")
@ApplicationScoped
-public class HttpService {
- @Path("/get")
- @GET
- @Produces(MediaType.TEXT_PLAIN)
- public String get() {
- return "get";
+public class VertxClientRelatedBeansProducer {
+
+ @Singleton
+ @Produces
+ @Named("myVertxOptions")
+ VertxOptions createOptions() {
+ // Setting an inconsistent value to generate an
IllegalArgumentException on first Vertx.x HTTP client request
+ return new VertxOptions().setMaxEventLoopExecuteTime(0);
}
- @Path("/toUpper")
- @POST
- @Consumes(MediaType.TEXT_PLAIN)
- @Produces(MediaType.TEXT_PLAIN)
- public String toUpper(String message) {
- return message.toUpperCase();
+ @ApplicationScoped
+ @Produces
+ @Named("myVertxCookieStore")
+ CookieStore createCookieStore() {
+ return CookieStore.build();
}
+
}
diff --git a/integration-tests/http/src/main/resources/application.properties
b/integration-tests/http/src/main/resources/application.properties
index ba7b64fb33..ed8496c3a9 100644
--- a/integration-tests/http/src/main/resources/application.properties
+++ b/integration-tests/http/src/main/resources/application.properties
@@ -19,6 +19,7 @@
# Quarkus
#
quarkus.native.resources.includes = jsse/*,restcountries/*
+quarkus.native.add-all-charsets = true
quarkus.camel.native.reflection.serialization-enabled = true
# Basic authentication configuration
diff --git
a/integration-tests/http/src/test/java/org/apache/camel/quarkus/component/http/it/HttpTest.java
b/integration-tests/http/src/test/java/org/apache/camel/quarkus/component/http/it/HttpTest.java
index e9d330bc5f..f8280a3383 100644
---
a/integration-tests/http/src/test/java/org/apache/camel/quarkus/component/http/it/HttpTest.java
+++
b/integration-tests/http/src/test/java/org/apache/camel/quarkus/component/http/it/HttpTest.java
@@ -34,6 +34,7 @@ import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.empty;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.not;
+import static org.junit.jupiter.api.Assertions.assertArrayEquals;
@QuarkusTest
@QuarkusTestResource(HttpTestResource.class)
@@ -220,6 +221,72 @@ class HttpTest {
.body(is("Handled HttpOperationFailedException"));
}
+ @Test
+ public void vertxHttpMultipartFormParamsShouldSucceed() {
+ RestAssured
+ .given()
+ .queryParam("test-port", RestAssured.port)
+ .queryParam("organization", "Apache")
+ .queryParam("project", "Camel")
+ .when()
+ .get("/test/client/vertx-http/multipart-form-params")
+ .then()
+ .statusCode(200)
+ .body(is("multipartFormParams(Apache, Camel)"));
+ }
+
+ @Test
+ public void vertxHttpMultipartFormDataShouldSucceed() {
+ RestAssured
+ .given()
+ .queryParam("test-port", RestAssured.port)
+ .when()
+ .get("/test/client/vertx-http/multipart-form-data")
+ .then()
+ .statusCode(200)
+ .body(is("multipartFormData(part1=content1, <part2
value=\"content2\"/>)"));
+ }
+
+ @Test
+ public void vertxHttpCustomVertxOptionsShouldSucceed() {
+ RestAssured
+ .given()
+ .queryParam("test-port", RestAssured.port)
+ .when()
+ .get("/test/client/vertx-http/custom-vertx-options")
+ .then()
+ .statusCode(200)
+ .body(is("OK: the custom vertxOptions has triggered the
expected exception"));
+ }
+
+ @Test
+ public void vertxHttpSessionManagementShouldReturnSecretContent() {
+ RestAssured
+ .given()
+ .queryParam("test-port", RestAssured.port)
+ .when()
+ .get("/test/client/vertx-http/session-management")
+ .then()
+ .statusCode(200)
+ .body(is("Some secret content"));
+ }
+
+ @Test
+ public void vertxHttpBufferConversionWithCharset() {
+ byte[] actualBytes = RestAssured
+ .given()
+ .queryParam("string", "special char €")
+ .queryParam("charset", "iso-8859-15")
+ .when()
+ .get("/test/client/vertx-http/buffer-conversion-with-charset")
+ .then()
+ .statusCode(200)
+ .extract().asByteArray();
+
+ byte[] expectedBytes = new byte[] { 115, 112, 101, 99, 105, 97, 108,
32, 99, 104, 97, 114, 32, -92 };
+ assertArrayEquals(expectedBytes, actualBytes);
+ }
+
private Integer getPort() {
return getPort("camel.netty-http.test-port");
}