+ * Note that the Infinispan client must be configured to so that the user has necessary permissions
+ * on the Infinispan server. The required minimum is the Infinispan {@code deployer} role.
+ */
+ @ConfigItem
+ public Optional
+ * In this mode, if an application is deployed in multiple replicas fronted with a load balancer, + * it is necessary to enable sticky sessions (also known as session affinity) on the load balancer. + * Still, losing a replica means losing all sessions stored on that replica. + *
+ * In a multi-replica deployment, it is recommended to use an external session store (Redis or Infinispan). + * Alternatively, if Vert.x clustering is enabled ({@code quarkus.vertx.cluster}), in-memory sessions + * may be clustered ({@code quarkus.http.sessions.in-memory.clustered}), which also makes sticky sessions + * not necessary and prevents session data loss (depending on the Vert.x cluster manager configuration). + */ + IN_MEMORY, + /** + * Support for Vert.x Web sessions is enabled and sessions are stored in a remote Redis server. + * The Quarkus Redis Client extension must be present and a Redis connection must be configured. + */ + REDIS, + /** + * Support for Vert.x Web sessions is enabled and sessions are stored in a remote Infinispan cache. + * The Quarkus Infinispan Client extension must be present and an Infinispan connection must be configured. + */ + INFINISPAN, + } +} diff --git a/extensions/vertx-http/runtime/src/main/java/io/quarkus/vertx/http/runtime/SessionsConfig.java b/extensions/vertx-http/runtime/src/main/java/io/quarkus/vertx/http/runtime/SessionsConfig.java new file mode 100644 index 00000000000000..7e6dda44fe7743 --- /dev/null +++ b/extensions/vertx-http/runtime/src/main/java/io/quarkus/vertx/http/runtime/SessionsConfig.java @@ -0,0 +1,102 @@ +package io.quarkus.vertx.http.runtime; + +import java.time.Duration; +import java.util.Optional; + +import io.quarkus.runtime.annotations.ConfigGroup; +import io.quarkus.runtime.annotations.ConfigItem; +import io.vertx.core.http.CookieSameSite; + +/** + * Configuration of Vert.x Web sessions. + */ +@ConfigGroup +public class SessionsConfig { + /** + * The session timeout. + */ + @ConfigItem(defaultValue = "30M") + public Duration timeout; + + /** + * The requested length of the session identifier. + */ + @ConfigItem(defaultValue = "16") + public int idLength; + + /** + * The session cookie path. The value is relative to {@code quarkus.http.root-path}. + */ + @ConfigItem(defaultValue = "/") + public String path; + + /** + * The name of the session cookie. + */ + @ConfigItem(defaultValue = "JSESSIONID") + public String cookieName; + + /** + * Whether the session cookie has the {@code HttpOnly} attribute. + */ + @ConfigItem(defaultValue = "true") + public boolean cookieHttpOnly; + + /** + * Whether the session cookie has the {@code Secure} attribute. + *
+ * Ignored when Vert.x clustering is not enabled. + */ + @ConfigItem(defaultValue = "false") + public boolean clustered; + + /** + * Maximum time to retry when retrieving session data from the cluster-wide map. + * The Vert.x session handler retries when the session data are not found, because + * distributing data across the cluster may take time. + *
+ * Ignored when in-memory sessions are not clustered.
+ */
+ @ConfigItem(defaultValue = "5s")
+ public Duration retryTimeout;
+}
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 fbcb893f48b9dc..054edbe294ba6c 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
@@ -7,6 +7,7 @@
import java.net.BindException;
import java.net.URI;
import java.net.URISyntaxException;
+import java.time.Duration;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
@@ -104,6 +105,10 @@
import io.vertx.ext.web.RoutingContext;
import io.vertx.ext.web.handler.BodyHandler;
import io.vertx.ext.web.handler.CorsHandler;
+import io.vertx.ext.web.handler.SessionHandler;
+import io.vertx.ext.web.sstore.ClusteredSessionStore;
+import io.vertx.ext.web.sstore.LocalSessionStore;
+import io.vertx.ext.web.sstore.SessionStore;
@Recorder
public class VertxHttpRecorder {
@@ -191,14 +196,18 @@ private boolean uriValid(HttpServerRequest httpServerRequest) {
final RuntimeValue