diff --git a/extensions/websockets-next/deployment/src/test/java/io/quarkus/websockets/next/test/maxframesize/MaxFrameSizeTest.java b/extensions/websockets-next/deployment/src/test/java/io/quarkus/websockets/next/test/maxframesize/MaxFrameSizeTest.java new file mode 100644 index 0000000000000..07b36da147bfc --- /dev/null +++ b/extensions/websockets-next/deployment/src/test/java/io/quarkus/websockets/next/test/maxframesize/MaxFrameSizeTest.java @@ -0,0 +1,66 @@ +package io.quarkus.websockets.next.test.maxframesize; + +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.net.URI; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; + +import jakarta.inject.Inject; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; + +import io.netty.handler.codec.http.websocketx.CorruptedWebSocketFrameException; +import io.quarkus.test.QuarkusUnitTest; +import io.quarkus.test.common.http.TestHTTPResource; +import io.quarkus.websockets.next.OnError; +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; +import io.vertx.core.http.WebSocketFrame; + +public class MaxFrameSizeTest { + + @RegisterExtension + public static final QuarkusUnitTest test = new QuarkusUnitTest() + .withApplicationRoot(root -> { + root.addClasses(Echo.class, WSClient.class); + }) + .overrideConfigKey("quarkus.websockets-next.server.max-frame-size", "10"); + + @Inject + Vertx vertx; + + @TestHTTPResource("/echo") + URI echoUri; + + @Test + void testMaxFrameSize() throws InterruptedException, ExecutionException, TimeoutException { + WSClient client = WSClient.create(vertx).connect(echoUri); + client.socket().writeFrame(WebSocketFrame.textFrame("foo".repeat(10), false)); + assertTrue(Echo.CORRUPTED_LATCH.await(5, TimeUnit.SECONDS)); + } + + @WebSocket(path = "/echo") + public static class Echo { + + static final CountDownLatch CORRUPTED_LATCH = new CountDownLatch(1); + + @OnTextMessage + String process(String message) { + return message; + } + + @OnError + void onError(CorruptedWebSocketFrameException e) { + // Note that connection is automatically closed when CorruptedWebSocketFrameException is thrown + CORRUPTED_LATCH.countDown(); + } + + } + +} diff --git a/extensions/websockets-next/deployment/src/test/java/io/quarkus/websockets/next/test/utils/WSClient.java b/extensions/websockets-next/deployment/src/test/java/io/quarkus/websockets/next/test/utils/WSClient.java index 926c0d1b82d15..49f123a443e22 100644 --- a/extensions/websockets-next/deployment/src/test/java/io/quarkus/websockets/next/test/utils/WSClient.java +++ b/extensions/websockets-next/deployment/src/test/java/io/quarkus/websockets/next/test/utils/WSClient.java @@ -164,6 +164,10 @@ public void close() { disconnect(); } + public WebSocket socket() { + return socket.get(); + } + public enum ReceiverMode { BINARY, TEXT, 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 cd37858a15a11..f8f3f27895713 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 @@ -153,6 +153,9 @@ protected WebSocketClientOptions populateClientOptions() { if (config.maxMessageSize().isPresent()) { clientOptions.setMaxMessageSize(config.maxMessageSize().getAsInt()); } + if (config.maxFrameSize().isPresent()) { + clientOptions.setMaxFrameSize(config.maxFrameSize().getAsInt()); + } Optional maybeTlsConfiguration = TlsConfiguration.from(tlsConfigurationRegistry, config.tlsConfigurationName()); diff --git a/extensions/websockets-next/runtime/src/main/java/io/quarkus/websockets/next/runtime/WebSocketHttpServerOptionsCustomizer.java b/extensions/websockets-next/runtime/src/main/java/io/quarkus/websockets/next/runtime/WebSocketHttpServerOptionsCustomizer.java index c2d2a89b6b626..228a7051f7d19 100644 --- a/extensions/websockets-next/runtime/src/main/java/io/quarkus/websockets/next/runtime/WebSocketHttpServerOptionsCustomizer.java +++ b/extensions/websockets-next/runtime/src/main/java/io/quarkus/websockets/next/runtime/WebSocketHttpServerOptionsCustomizer.java @@ -34,6 +34,9 @@ private void customize(HttpServerOptions options) { if (config.maxMessageSize().isPresent()) { options.setMaxWebSocketMessageSize(config.maxMessageSize().getAsInt()); } + if (config.maxFrameSize().isPresent()) { + options.setMaxWebSocketFrameSize(config.maxFrameSize().getAsInt()); + } } } diff --git a/extensions/websockets-next/runtime/src/main/java/io/quarkus/websockets/next/runtime/config/WebSocketsClientRuntimeConfig.java b/extensions/websockets-next/runtime/src/main/java/io/quarkus/websockets/next/runtime/config/WebSocketsClientRuntimeConfig.java index 2b5614984ec47..9ee48f5914656 100644 --- a/extensions/websockets-next/runtime/src/main/java/io/quarkus/websockets/next/runtime/config/WebSocketsClientRuntimeConfig.java +++ b/extensions/websockets-next/runtime/src/main/java/io/quarkus/websockets/next/runtime/config/WebSocketsClientRuntimeConfig.java @@ -34,6 +34,12 @@ public interface WebSocketsClientRuntimeConfig { */ OptionalInt maxMessageSize(); + /** + * The maximum size of a frame in bytes. The default values is + * {@value io.vertx.core.http.HttpClientOptions#DEFAULT_MAX_WEBSOCKET_FRAME_SIZEX}. + */ + OptionalInt maxFrameSize(); + /** * The interval after which, when set, the client sends a ping message to a connected server automatically. *

diff --git a/extensions/websockets-next/runtime/src/main/java/io/quarkus/websockets/next/runtime/config/WebSocketsServerRuntimeConfig.java b/extensions/websockets-next/runtime/src/main/java/io/quarkus/websockets/next/runtime/config/WebSocketsServerRuntimeConfig.java index 62f4edcce37ed..5284d7d022449 100644 --- a/extensions/websockets-next/runtime/src/main/java/io/quarkus/websockets/next/runtime/config/WebSocketsServerRuntimeConfig.java +++ b/extensions/websockets-next/runtime/src/main/java/io/quarkus/websockets/next/runtime/config/WebSocketsServerRuntimeConfig.java @@ -40,6 +40,12 @@ public interface WebSocketsServerRuntimeConfig { */ OptionalInt maxMessageSize(); + /** + * The maximum size of a frame in bytes. The default values is + * {@value io.vertx.core.http.HttpServerOptions#DEFAULT_MAX_WEBSOCKET_FRAME_SIZE}. + */ + OptionalInt maxFrameSize(); + /** * The interval after which, when set, the server sends a ping message to a connected client automatically. *