diff --git a/bom/application/pom.xml b/bom/application/pom.xml index f4d30f99a4447..8ab52865056b4 100644 --- a/bom/application/pom.xml +++ b/bom/application/pom.xml @@ -46,7 +46,7 @@ 2.1.22 1.6.0 2.1.0 - 5.4.0 + 5.4.1 3.5.1 1.2.2 1.0.13 diff --git a/docs/src/main/asciidoc/http-reference.adoc b/docs/src/main/asciidoc/http-reference.adoc index d978e3cfe2c88..5a1f3e318fb00 100644 --- a/docs/src/main/asciidoc/http-reference.adoc +++ b/docs/src/main/asciidoc/http-reference.adoc @@ -245,6 +245,16 @@ Will include the `Cache-Control: max-age=1` header when `/paths/order` is reques include::{generated-dir}/config/quarkus-vertx-http-config-group-filter-config.adoc[leveloffset=+1, opts=optional] +== Support 100-Continue in vert.x + +In order to support `100-continue`, the `quarkus.http.handle-100-continue-automatically` option needs to be enabled explicitly +For additional information check https://datatracker.ietf.org/doc/html/rfc7231#section-5.1.1[100-continue= and the related +https://vertx.io/docs/apidocs/io/vertx/core/http/HttpServerOptions.html#DEFAULT_HANDLE_100_CONTINE_AUTOMATICALLY[Vert.x documentation]. + +[source,properties] +---- +quarkus.http.handle-100-continue-automatically=true +---- == HTTP/2 Support diff --git a/extensions/smallrye-fault-tolerance/deployment/src/main/java/io/quarkus/smallrye/faulttolerance/deployment/FaultToleranceScanner.java b/extensions/smallrye-fault-tolerance/deployment/src/main/java/io/quarkus/smallrye/faulttolerance/deployment/FaultToleranceScanner.java index e6dbcce1a75f1..c400b66bb8977 100644 --- a/extensions/smallrye-fault-tolerance/deployment/src/main/java/io/quarkus/smallrye/faulttolerance/deployment/FaultToleranceScanner.java +++ b/extensions/smallrye-fault-tolerance/deployment/src/main/java/io/quarkus/smallrye/faulttolerance/deployment/FaultToleranceScanner.java @@ -24,6 +24,7 @@ import io.quarkus.gizmo.ClassOutput; import io.smallrye.common.annotation.Blocking; import io.smallrye.common.annotation.NonBlocking; +import io.smallrye.faulttolerance.api.ApplyFaultTolerance; import io.smallrye.faulttolerance.api.CircuitBreakerName; import io.smallrye.faulttolerance.api.CustomBackoff; import io.smallrye.faulttolerance.api.ExponentialBackoff; @@ -119,6 +120,7 @@ FaultToleranceMethod createFaultToleranceMethod(ClassInfo beanClass, MethodInfo result.retry = getAnnotation(Retry.class, method, beanClass, annotationsPresentDirectly); result.timeout = getAnnotation(Timeout.class, method, beanClass, annotationsPresentDirectly); + result.applyFaultTolerance = getAnnotation(ApplyFaultTolerance.class, method, beanClass, annotationsPresentDirectly); result.circuitBreakerName = getAnnotation(CircuitBreakerName.class, method, beanClass, annotationsPresentDirectly); result.customBackoff = getAnnotation(CustomBackoff.class, method, beanClass, annotationsPresentDirectly); result.exponentialBackoff = getAnnotation(ExponentialBackoff.class, method, beanClass, annotationsPresentDirectly); diff --git a/extensions/vertx-http/deployment/src/test/java/io/quarkus/vertx/http/HttpContinueHeaderTest.java b/extensions/vertx-http/deployment/src/test/java/io/quarkus/vertx/http/HttpContinueHeaderTest.java new file mode 100644 index 0000000000000..a2b4220cda4d6 --- /dev/null +++ b/extensions/vertx-http/deployment/src/test/java/io/quarkus/vertx/http/HttpContinueHeaderTest.java @@ -0,0 +1,67 @@ +package io.quarkus.vertx.http; + +import java.net.Socket; +import java.net.URL; +import java.nio.charset.StandardCharsets; + +import javax.enterprise.context.ApplicationScoped; +import javax.enterprise.event.Observes; + +import org.jboss.shrinkwrap.api.asset.StringAsset; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; + +import io.quarkus.test.QuarkusUnitTest; +import io.quarkus.test.common.http.TestHTTPResource; +import io.vertx.core.Handler; +import io.vertx.ext.web.Router; +import io.vertx.ext.web.RoutingContext; + +public class HttpContinueHeaderTest { + private static final String APP_PROPS = "quarkus.http.handle-100-continue-automatically=true\n"; + + @RegisterExtension + static final QuarkusUnitTest config = new QuarkusUnitTest() + .withApplicationRoot((jar) -> jar + .addAsResource(new StringAsset(APP_PROPS), "application.properties") + .addClasses(HttpContinueHeaderTest.BeanRegisteringRouteUsingObserves.class)); + + @TestHTTPResource + URL uri; + + @Test + public void testConnection() throws Exception { + try (Socket one = new Socket(uri.getHost(), uri.getPort())) { + one.getOutputStream().write("GET /hello HTTP/1.1\r\nExpect: 100-continue\r\nHost: localhost\r\n\r\n" + .getBytes(StandardCharsets.UTF_8)); + + StringBuilder sb = new StringBuilder(); + byte[] data = new byte[1024]; + int j; + while (!sb.toString().endsWith("hello")) { + j = one.getInputStream().read(data); + if (j == -1) { + Assertions.fail("Did not read full HTTP response"); + } + sb.append(new String(data, 0, j, StandardCharsets.US_ASCII)); + } + Assertions.assertTrue(sb.toString().contains("HTTP/1.1 100 Continue")); + Assertions.assertTrue(sb.toString().contains("HTTP/1.1 200 OK")); + } + } + + @ApplicationScoped + static class BeanRegisteringRouteUsingObserves { + + public void register(@Observes Router router) { + router.route("/hello").handler(new Handler() { + @Override + public void handle(RoutingContext event) { + event.end("hello"); + } + }); + + } + } +} diff --git a/extensions/vertx-http/runtime/src/main/java/io/quarkus/vertx/http/runtime/HttpConfiguration.java b/extensions/vertx-http/runtime/src/main/java/io/quarkus/vertx/http/runtime/HttpConfiguration.java index 390a998fba1b1..86e6eb7d89581 100644 --- a/extensions/vertx-http/runtime/src/main/java/io/quarkus/vertx/http/runtime/HttpConfiguration.java +++ b/extensions/vertx-http/runtime/src/main/java/io/quarkus/vertx/http/runtime/HttpConfiguration.java @@ -91,6 +91,13 @@ public class HttpConfiguration { */ public ServerSslConfig ssl; + /** + * When set to {@code true}, the HTTP server automatically sends `100 CONTINUE` + * response when the request expects it (with the `Expect: 100-Continue` header). + */ + @ConfigItem(defaultValue = "false", name = "handle-100-continue-automatically") + public boolean handle100ContinueAutomatically; + /** * The number if IO threads used to perform IO. This will be automatically set to a reasonable value based on * the number of CPU cores if it is not provided. If this is set to a higher value than the number of Vert.x event diff --git a/extensions/vertx-http/runtime/src/main/java/io/quarkus/vertx/http/runtime/VertxHttpRecorder.java b/extensions/vertx-http/runtime/src/main/java/io/quarkus/vertx/http/runtime/VertxHttpRecorder.java index 6461421dd98b2..4e39609925fa9 100644 --- a/extensions/vertx-http/runtime/src/main/java/io/quarkus/vertx/http/runtime/VertxHttpRecorder.java +++ b/extensions/vertx-http/runtime/src/main/java/io/quarkus/vertx/http/runtime/VertxHttpRecorder.java @@ -861,6 +861,7 @@ private static void applyCommonOptions(HttpServerOptions httpServerOptions, } httpServerOptions.setDecompressionSupported(buildTimeConfig.enableDecompression); httpServerOptions.setMaxInitialLineLength(httpConfiguration.limits.maxInitialLineLength); + httpServerOptions.setHandle100ContinueAutomatically(httpConfiguration.handle100ContinueAutomatically); } private static KeyStoreOptions createKeyStoreOptions(Path path, String password, Optional fileType,