Allow to turn off Utf8FrameValidator creation for websocket with Bina… (#9417)
…ryWebSocketFrames Motivation: `Utf8FrameValidator` is always created and added to the pipeline in `WebSocketServerProtocolHandler.handlerAdded` method. However, for websocket connection with only `BinaryWebSocketFrame`'s UTF8 validator is unnecessary overhead. Adding of `Utf8FrameValidator` could be easily avoided by extending of `WebSocketDecoderConfig` with additional property. Specification requires UTF-8 validation only for `TextWebSocketFrame`. Modification: Added `boolean WebSocketDecoderConfig.withUTF8Validator` that allows to avoid adding of `Utf8FrameValidator` during pipeline initialization. Result: Less overhead when using only `BinaryWebSocketFrame`within web socket.
This commit is contained in:
parent
ca2e8c3b69
commit
10ee697557
|
@ -27,6 +27,7 @@ public final class WebSocketDecoderConfig {
|
||||||
private final boolean allowMaskMismatch;
|
private final boolean allowMaskMismatch;
|
||||||
private final boolean allowExtensions;
|
private final boolean allowExtensions;
|
||||||
private final boolean closeOnProtocolViolation;
|
private final boolean closeOnProtocolViolation;
|
||||||
|
private final boolean withUTF8Validator;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor
|
* Constructor
|
||||||
|
@ -44,14 +45,20 @@ public final class WebSocketDecoderConfig {
|
||||||
* Flag to allow reserved extension bits to be used or not
|
* Flag to allow reserved extension bits to be used or not
|
||||||
* @param closeOnProtocolViolation
|
* @param closeOnProtocolViolation
|
||||||
* Flag to send close frame immediately on any protocol violation.ion.
|
* 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,
|
private WebSocketDecoderConfig(int maxFramePayloadLength, boolean expectMaskedFrames, boolean allowMaskMismatch,
|
||||||
boolean allowExtensions, boolean closeOnProtocolViolation) {
|
boolean allowExtensions, boolean closeOnProtocolViolation,
|
||||||
|
boolean withUTF8Validator) {
|
||||||
this.maxFramePayloadLength = maxFramePayloadLength;
|
this.maxFramePayloadLength = maxFramePayloadLength;
|
||||||
this.expectMaskedFrames = expectMaskedFrames;
|
this.expectMaskedFrames = expectMaskedFrames;
|
||||||
this.allowMaskMismatch = allowMaskMismatch;
|
this.allowMaskMismatch = allowMaskMismatch;
|
||||||
this.allowExtensions = allowExtensions;
|
this.allowExtensions = allowExtensions;
|
||||||
this.closeOnProtocolViolation = closeOnProtocolViolation;
|
this.closeOnProtocolViolation = closeOnProtocolViolation;
|
||||||
|
this.withUTF8Validator = withUTF8Validator;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int maxFramePayloadLength() {
|
public int maxFramePayloadLength() {
|
||||||
|
@ -74,6 +81,10 @@ public final class WebSocketDecoderConfig {
|
||||||
return closeOnProtocolViolation;
|
return closeOnProtocolViolation;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean withUTF8Validator() {
|
||||||
|
return withUTF8Validator;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "WebSocketDecoderConfig" +
|
return "WebSocketDecoderConfig" +
|
||||||
|
@ -82,6 +93,7 @@ public final class WebSocketDecoderConfig {
|
||||||
", allowMaskMismatch=" + allowMaskMismatch +
|
", allowMaskMismatch=" + allowMaskMismatch +
|
||||||
", allowExtensions=" + allowExtensions +
|
", allowExtensions=" + allowExtensions +
|
||||||
", closeOnProtocolViolation=" + closeOnProtocolViolation +
|
", closeOnProtocolViolation=" + closeOnProtocolViolation +
|
||||||
|
", withUTF8Validator=" + withUTF8Validator +
|
||||||
"]";
|
"]";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -99,6 +111,7 @@ public final class WebSocketDecoderConfig {
|
||||||
private boolean allowMaskMismatch;
|
private boolean allowMaskMismatch;
|
||||||
private boolean allowExtensions;
|
private boolean allowExtensions;
|
||||||
private boolean closeOnProtocolViolation = true;
|
private boolean closeOnProtocolViolation = true;
|
||||||
|
private boolean withUTF8Validator = true;
|
||||||
|
|
||||||
private Builder() {
|
private Builder() {
|
||||||
/* No-op */
|
/* No-op */
|
||||||
|
@ -111,6 +124,7 @@ public final class WebSocketDecoderConfig {
|
||||||
allowMaskMismatch = decoderConfig.allowMaskMismatch();
|
allowMaskMismatch = decoderConfig.allowMaskMismatch();
|
||||||
allowExtensions = decoderConfig.allowExtensions();
|
allowExtensions = decoderConfig.allowExtensions();
|
||||||
closeOnProtocolViolation = decoderConfig.closeOnProtocolViolation();
|
closeOnProtocolViolation = decoderConfig.closeOnProtocolViolation();
|
||||||
|
withUTF8Validator = decoderConfig.withUTF8Validator();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Builder maxFramePayloadLength(int maxFramePayloadLength) {
|
public Builder maxFramePayloadLength(int maxFramePayloadLength) {
|
||||||
|
@ -138,10 +152,15 @@ public final class WebSocketDecoderConfig {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Builder withUTF8Validator(boolean withUTF8Validator) {
|
||||||
|
this.withUTF8Validator = withUTF8Validator;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
public WebSocketDecoderConfig build() {
|
public WebSocketDecoderConfig build() {
|
||||||
return new WebSocketDecoderConfig(
|
return new WebSocketDecoderConfig(
|
||||||
maxFramePayloadLength, expectMaskedFrames, allowMaskMismatch,
|
maxFramePayloadLength, expectMaskedFrames, allowMaskMismatch,
|
||||||
allowExtensions, closeOnProtocolViolation);
|
allowExtensions, closeOnProtocolViolation, withUTF8Validator);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -216,7 +216,7 @@ public class WebSocketServerProtocolHandler extends WebSocketProtocolHandler {
|
||||||
new WebSocketServerProtocolHandshakeHandler(
|
new WebSocketServerProtocolHandshakeHandler(
|
||||||
websocketPath, subprotocols, checkStartsWith, handshakeTimeoutMillis, decoderConfig));
|
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.
|
// Add the UFT8 checking before this one.
|
||||||
cp.addBefore(ctx.name(), Utf8FrameValidator.class.getName(),
|
cp.addBefore(ctx.name(), Utf8FrameValidator.class.getName(),
|
||||||
new Utf8FrameValidator());
|
new Utf8FrameValidator());
|
||||||
|
|
|
@ -120,6 +120,46 @@ public class WebSocketServerProtocolHandlerTest {
|
||||||
assertFalse(ch.finish());
|
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
|
@Test
|
||||||
public void testHandleTextFrame() {
|
public void testHandleTextFrame() {
|
||||||
CustomTextFrameHandler customTextFrameHandler = new CustomTextFrameHandler();
|
CustomTextFrameHandler customTextFrameHandler = new CustomTextFrameHandler();
|
||||||
|
|
Loading…
Reference in New Issue
Block a user