Skip to content

Commit

Permalink
Complete vertx-http test coverage #4658
Browse files Browse the repository at this point in the history
  • Loading branch information
aldettinger committed Mar 29, 2023
1 parent 7b9aaa1 commit 9e0a7f8
Show file tree
Hide file tree
Showing 9 changed files with 313 additions and 0 deletions.
15 changes: 15 additions & 0 deletions docs/modules/ROOT/pages/reference/extensions/vertx-http.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -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.

8 changes: 8 additions & 0 deletions extensions/vertx-http/runtime/src/main/doc/configuration.adoc
Original file line number Diff line number Diff line change
@@ -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.
10 changes: 10 additions & 0 deletions integration-tests/http/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,16 @@
<artifactId>quarkus-junit4-mock</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-multipart-provider</artifactId>
<exclusions>
<exclusion>
<groupId>jakarta.activation</groupId>
<artifactId>jakarta.activation-api</artifactId>
</exclusion>
</exclusions>
</dependency>

<!-- test dependencies - camel-quarkus -->
<dependency>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,16 +36,24 @@
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;

import io.vertx.core.buffer.Buffer;
import io.vertx.ext.web.multipart.MultipartForm;
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 {
Expand Down Expand Up @@ -379,6 +387,105 @@ public String vertxHttpSerializedException(@QueryParam("test-port") int port) {
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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import javax.inject.Named;

import io.quarkus.runtime.annotations.RegisterForReflection;
import io.vertx.core.buffer.Buffer;
import org.apache.camel.Exchange;
import org.apache.camel.Processor;
import org.apache.camel.builder.RouteBuilder;
Expand Down Expand Up @@ -77,6 +78,8 @@ public void process(Exchange exchange) throws Exception {
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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,21 @@
*/
package org.apache.camel.quarkus.component.http.it;

import java.util.Map;

import javax.enterprise.context.ApplicationScoped;
import javax.ws.rs.Consumes;
import javax.ws.rs.CookieParam;
import javax.ws.rs.ForbiddenException;
import javax.ws.rs.FormParam;
import javax.ws.rs.GET;
import javax.ws.rs.HeaderParam;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.NewCookie;
import javax.ws.rs.core.Response;

@Path("/service")
@ApplicationScoped
Expand All @@ -41,4 +49,53 @@ public String get() {
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("sessionId", "my-session-id-123");
return Response.ok().cookie(cookie).build();
}
throw new ForbiddenException("Wrong username/password, no cookie will be created");
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.camel.quarkus.component.http.it;

import javax.enterprise.context.ApplicationScoped;
import javax.inject.Named;
import javax.inject.Singleton;
import javax.ws.rs.Produces;

import io.vertx.core.VertxOptions;
import io.vertx.ext.web.client.spi.CookieStore;

@ApplicationScoped
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);
}

@ApplicationScoped
@Produces
@Named("myVertxCookieStore")
CookieStore createCookieStore() {
return CookieStore.build();
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down

0 comments on commit 9e0a7f8

Please sign in to comment.