From 6c6a5a41ea6730926d9ff82131559dd75b1fe61d Mon Sep 17 00:00:00 2001 From: Martin Kouba Date: Wed, 28 Aug 2024 11:32:44 +0200 Subject: [PATCH] WebSockets Next: support endpoints with empty path - fixes #42808 --- .../next/deployment/WebSocketProcessor.java | 3 + .../client/ClientEndpointEmptyPathTest.java | 94 +++++++++++++++++++ .../next/runtime/WebSocketConnectorBase.java | 3 + 3 files changed, 100 insertions(+) create mode 100644 extensions/websockets-next/deployment/src/test/java/io/quarkus/websockets/next/test/client/ClientEndpointEmptyPathTest.java 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 cf2040a7e2c2a8..39a73e19e1293f 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 @@ -599,6 +599,9 @@ static String mergePath(String prefix, String path) { } static String getPath(String path) { + if (path.isEmpty()) { + return ""; + } StringBuilder sb = new StringBuilder(); Matcher m = PATH_PARAM_PATTERN.matcher(path); while (m.find()) { diff --git a/extensions/websockets-next/deployment/src/test/java/io/quarkus/websockets/next/test/client/ClientEndpointEmptyPathTest.java b/extensions/websockets-next/deployment/src/test/java/io/quarkus/websockets/next/test/client/ClientEndpointEmptyPathTest.java new file mode 100644 index 00000000000000..c166af3e8362bb --- /dev/null +++ b/extensions/websockets-next/deployment/src/test/java/io/quarkus/websockets/next/test/client/ClientEndpointEmptyPathTest.java @@ -0,0 +1,94 @@ +package io.quarkus.websockets.next.test.client; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.net.URI; +import java.util.List; +import java.util.concurrent.CopyOnWriteArrayList; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; + +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.OnClose; +import io.quarkus.websockets.next.OnTextMessage; +import io.quarkus.websockets.next.WebSocket; +import io.quarkus.websockets.next.WebSocketClient; +import io.quarkus.websockets.next.WebSocketClientConnection; +import io.quarkus.websockets.next.WebSocketConnector; + +public class ClientEndpointEmptyPathTest { + + @RegisterExtension + public static final QuarkusUnitTest test = new QuarkusUnitTest() + .withApplicationRoot(root -> { + root.addClasses(ServerEndpoint.class, ClientEndpoint.class); + }); + + @Inject + WebSocketConnector connector; + + @TestHTTPResource("/") + URI uri; + + @Test + void testClient() throws InterruptedException { + WebSocketClientConnection connection = connector + .baseUri(uri) + .connectAndAwait(); + connection.sendTextAndAwait("Hi!"); + + assertTrue(ClientEndpoint.MESSAGE_LATCH.await(5, TimeUnit.SECONDS)); + assertEquals("Hi!", ClientEndpoint.MESSAGES.get(0)); + + connection.closeAndAwait(); + assertTrue(ClientEndpoint.CLOSED_LATCH.await(5, TimeUnit.SECONDS)); + assertTrue(ServerEndpoint.CLOSED_LATCH.await(5, TimeUnit.SECONDS)); + } + + @WebSocket(path = "") + public static class ServerEndpoint { + + static final CountDownLatch CLOSED_LATCH = new CountDownLatch(1); + + @OnTextMessage + String echo(String message) { + return message; + } + + @OnClose + void close() { + CLOSED_LATCH.countDown(); + } + + } + + @WebSocketClient(path = "") + public static class ClientEndpoint { + + static final CountDownLatch MESSAGE_LATCH = new CountDownLatch(1); + + static final List MESSAGES = new CopyOnWriteArrayList<>(); + + static final CountDownLatch CLOSED_LATCH = new CountDownLatch(1); + + @OnTextMessage + void onMessage(String message, WebSocketClientConnection connection) { + MESSAGES.add(message); + MESSAGE_LATCH.countDown(); + } + + @OnClose + void close() { + CLOSED_LATCH.countDown(); + } + + } + +} diff --git a/extensions/websockets-next/runtime/src/main/java/io/quarkus/websockets/next/runtime/WebSocketConnectorBase.java b/extensions/websockets-next/runtime/src/main/java/io/quarkus/websockets/next/runtime/WebSocketConnectorBase.java index 1a878b6b6cb184..aa56b3af786da9 100644 --- a/extensions/websockets-next/runtime/src/main/java/io/quarkus/websockets/next/runtime/WebSocketConnectorBase.java +++ b/extensions/websockets-next/runtime/src/main/java/io/quarkus/websockets/next/runtime/WebSocketConnectorBase.java @@ -123,6 +123,9 @@ Set getPathParamNames(String path) { } String replacePathParameters(String path) { + if (path.isEmpty()) { + return ""; + } StringBuilder sb = new StringBuilder(); Matcher m = PATH_PARAM_PATTERN.matcher(path); while (m.find()) {