diff --git a/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketDecoderConfig.java b/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketDecoderConfig.java index d539458890..9d78834c4c 100644 --- a/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketDecoderConfig.java +++ b/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketDecoderConfig.java @@ -27,6 +27,7 @@ public final class WebSocketDecoderConfig { private final boolean allowMaskMismatch; private final boolean allowExtensions; private final boolean closeOnProtocolViolation; + private final boolean withUTF8Validator; /** * Constructor @@ -44,14 +45,20 @@ public final class WebSocketDecoderConfig { * Flag to allow reserved extension bits to be used or not * @param closeOnProtocolViolation * Flag to send close frame immediately on any protocol violation.ion. + * @param withUTF8Validator + * Allows you to avoid adding of Utf8FrameValidator to the pipeline on the + * WebSocketServerProtocolHandler creation. This is useful (less overhead) + * when you use only BinaryWebSocketFrame within your web socket connection. */ private WebSocketDecoderConfig(int maxFramePayloadLength, boolean expectMaskedFrames, boolean allowMaskMismatch, - boolean allowExtensions, boolean closeOnProtocolViolation) { + boolean allowExtensions, boolean closeOnProtocolViolation, + boolean withUTF8Validator) { this.maxFramePayloadLength = maxFramePayloadLength; this.expectMaskedFrames = expectMaskedFrames; this.allowMaskMismatch = allowMaskMismatch; this.allowExtensions = allowExtensions; this.closeOnProtocolViolation = closeOnProtocolViolation; + this.withUTF8Validator = withUTF8Validator; } public int maxFramePayloadLength() { @@ -74,6 +81,10 @@ public final class WebSocketDecoderConfig { return closeOnProtocolViolation; } + public boolean withUTF8Validator() { + return withUTF8Validator; + } + @Override public String toString() { return "WebSocketDecoderConfig" + @@ -82,6 +93,7 @@ public final class WebSocketDecoderConfig { ", allowMaskMismatch=" + allowMaskMismatch + ", allowExtensions=" + allowExtensions + ", closeOnProtocolViolation=" + closeOnProtocolViolation + + ", withUTF8Validator=" + withUTF8Validator + "]"; } @@ -99,6 +111,7 @@ public final class WebSocketDecoderConfig { private boolean allowMaskMismatch; private boolean allowExtensions; private boolean closeOnProtocolViolation = true; + private boolean withUTF8Validator = true; private Builder() { /* No-op */ @@ -111,6 +124,7 @@ public final class WebSocketDecoderConfig { allowMaskMismatch = decoderConfig.allowMaskMismatch(); allowExtensions = decoderConfig.allowExtensions(); closeOnProtocolViolation = decoderConfig.closeOnProtocolViolation(); + withUTF8Validator = decoderConfig.withUTF8Validator(); } public Builder maxFramePayloadLength(int maxFramePayloadLength) { @@ -138,10 +152,15 @@ public final class WebSocketDecoderConfig { return this; } + public Builder withUTF8Validator(boolean withUTF8Validator) { + this.withUTF8Validator = withUTF8Validator; + return this; + } + public WebSocketDecoderConfig build() { return new WebSocketDecoderConfig( - maxFramePayloadLength, expectMaskedFrames, allowMaskMismatch, - allowExtensions, closeOnProtocolViolation); + maxFramePayloadLength, expectMaskedFrames, allowMaskMismatch, + allowExtensions, closeOnProtocolViolation, withUTF8Validator); } } } diff --git a/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketServerProtocolHandler.java b/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketServerProtocolHandler.java index 42de7aff8a..68aae061ff 100644 --- a/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketServerProtocolHandler.java +++ b/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketServerProtocolHandler.java @@ -216,7 +216,7 @@ public class WebSocketServerProtocolHandler extends WebSocketProtocolHandler { new WebSocketServerProtocolHandshakeHandler( websocketPath, subprotocols, checkStartsWith, handshakeTimeoutMillis, decoderConfig)); } - if (cp.get(Utf8FrameValidator.class) == null) { + if (decoderConfig.withUTF8Validator() && cp.get(Utf8FrameValidator.class) == null) { // Add the UFT8 checking before this one. cp.addBefore(ctx.name(), Utf8FrameValidator.class.getName(), new Utf8FrameValidator()); diff --git a/codec-http/src/test/java/io/netty/handler/codec/http/websocketx/WebSocketServerProtocolHandlerTest.java b/codec-http/src/test/java/io/netty/handler/codec/http/websocketx/WebSocketServerProtocolHandlerTest.java index 69ec984974..0dd44ee7f7 100644 --- a/codec-http/src/test/java/io/netty/handler/codec/http/websocketx/WebSocketServerProtocolHandlerTest.java +++ b/codec-http/src/test/java/io/netty/handler/codec/http/websocketx/WebSocketServerProtocolHandlerTest.java @@ -120,6 +120,46 @@ public class WebSocketServerProtocolHandlerTest { assertFalse(ch.finish()); } + @Test + public void testCreateUTF8Validator() { + WebSocketDecoderConfig config = WebSocketDecoderConfig.newBuilder() + .withUTF8Validator(true) + .build(); + + EmbeddedChannel ch = new EmbeddedChannel( + new WebSocketServerProtocolHandler("/test", null, false, false, 1000L, config), + new HttpRequestDecoder(), + new HttpResponseEncoder(), + new MockOutboundHandler()); + writeUpgradeRequest(ch); + + FullHttpResponse response = responses.remove(); + assertEquals(SWITCHING_PROTOCOLS, response.status()); + response.release(); + + assertNotNull(ch.pipeline().get(Utf8FrameValidator.class)); + } + + @Test + public void testDoNotCreateUTF8Validator() { + WebSocketDecoderConfig config = WebSocketDecoderConfig.newBuilder() + .withUTF8Validator(false) + .build(); + + EmbeddedChannel ch = new EmbeddedChannel( + new WebSocketServerProtocolHandler("/test", null, false, false, 1000L, config), + new HttpRequestDecoder(), + new HttpResponseEncoder(), + new MockOutboundHandler()); + writeUpgradeRequest(ch); + + FullHttpResponse response = responses.remove(); + assertEquals(SWITCHING_PROTOCOLS, response.status()); + response.release(); + + assertNull(ch.pipeline().get(Utf8FrameValidator.class)); + } + @Test public void testHandleTextFrame() { CustomTextFrameHandler customTextFrameHandler = new CustomTextFrameHandler();