diff --git a/docs/src/main/asciidoc/websockets-next-reference.adoc b/docs/src/main/asciidoc/websockets-next-reference.adoc index 3ccf664f55127..322ac710d6a50 100644 --- a/docs/src/main/asciidoc/websockets-next-reference.adoc +++ b/docs/src/main/asciidoc/websockets-next-reference.adoc @@ -108,6 +108,8 @@ public class ChatWebSocket { Thus, client can connect to this web socket endpoint using `ws://localhost:8080/chat/your-name`. If TLS is used, the URL is `wss://localhost:8443/chat/your-name`. +NOTE: The endpoint path is relative to the xref:http-reference.adoc#context-path[root context] configured by the `quarkus.http.root-path` (which is `/` by default). For example, if you add `quarkus.http.root-path=/api` to your `application.properties` then a client can connect to this endpoint using `http://localhost:8080/api/chat/the-name`. + [[client-endpoints]] === Client endpoints diff --git a/extensions/websockets-next/deployment/src/main/java/io/quarkus/websockets/next/deployment/WebSocketProcessor.java b/extensions/websockets-next/deployment/src/main/java/io/quarkus/websockets/next/deployment/WebSocketProcessor.java index a6e5c44f375d7..cf2040a7e2c2a 100644 --- a/extensions/websockets-next/deployment/src/main/java/io/quarkus/websockets/next/deployment/WebSocketProcessor.java +++ b/extensions/websockets-next/deployment/src/main/java/io/quarkus/websockets/next/deployment/WebSocketProcessor.java @@ -86,7 +86,6 @@ import io.quarkus.security.spi.ClassSecurityCheckStorageBuildItem; import io.quarkus.security.spi.SecurityTransformerUtils; import io.quarkus.security.spi.runtime.SecurityCheck; -import io.quarkus.vertx.http.deployment.HttpRootPathBuildItem; import io.quarkus.vertx.http.deployment.RouteBuildItem; import io.quarkus.vertx.http.runtime.HandlerType; import io.quarkus.vertx.http.runtime.HttpBuildTimeConfig; @@ -445,18 +444,17 @@ public String apply(String name) { @Consume(SyntheticBeansRuntimeInitBuildItem.class) // SecurityHttpUpgradeCheck is runtime init due to runtime config @Record(RUNTIME_INIT) @BuildStep - public void registerRoutes(WebSocketServerRecorder recorder, HttpRootPathBuildItem httpRootPath, - List generatedEndpoints, HttpBuildTimeConfig httpConfig, Capabilities capabilities, + public void registerRoutes(WebSocketServerRecorder recorder, List generatedEndpoints, + HttpBuildTimeConfig httpConfig, Capabilities capabilities, BuildProducer routes) { for (GeneratedEndpointBuildItem endpoint : generatedEndpoints.stream().filter(GeneratedEndpointBuildItem::isServer) .toList()) { RouteBuildItem.Builder builder = RouteBuildItem.builder(); - String relativePath = httpRootPath.relativePath(endpoint.path); if (capabilities.isPresent(Capability.SECURITY) && !httpConfig.auth.proactive) { // Add a special handler so that it's possible to capture the SecurityIdentity before the HTTP upgrade - builder.routeFunction(relativePath, recorder.initializeSecurityHandler()); + builder.routeFunction(endpoint.path, recorder.initializeSecurityHandler()); } else { - builder.route(relativePath); + builder.route(endpoint.path); } builder .displayOnNotFoundPage("WebSocket Endpoint") diff --git a/extensions/websockets-next/deployment/src/test/java/io/quarkus/websockets/next/test/rootpath/CustomRootPathTest.java b/extensions/websockets-next/deployment/src/test/java/io/quarkus/websockets/next/test/rootpath/CustomRootPathTest.java new file mode 100644 index 0000000000000..fc76db5f64c9f --- /dev/null +++ b/extensions/websockets-next/deployment/src/test/java/io/quarkus/websockets/next/test/rootpath/CustomRootPathTest.java @@ -0,0 +1,52 @@ +package io.quarkus.websockets.next.test.rootpath; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.net.URI; + +import jakarta.inject.Inject; + +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.quarkus.websockets.next.OnTextMessage; +import io.quarkus.websockets.next.WebSocket; +import io.quarkus.websockets.next.test.utils.WSClient; +import io.vertx.core.Vertx; + +public class CustomRootPathTest { + + @RegisterExtension + public static final QuarkusUnitTest test = new QuarkusUnitTest() + .withApplicationRoot(root -> { + root.addClasses(Echo.class, WSClient.class); + }).overrideConfigKey("quarkus.http.root-path", "/api"); + + @Inject + Vertx vertx; + + @TestHTTPResource("echo") + URI testUri; + + @Test + void testEndpoint() { + assertTrue(testUri.toString().contains("/api")); + try (WSClient client = WSClient.create(vertx).connect(testUri)) { + assertEquals("monty", client.sendAndAwaitReply("monty").toString()); + } + } + + @WebSocket(path = "/echo") + public static class Echo { + + @OnTextMessage + String process(String message) throws InterruptedException { + return message; + } + + } + +}