Support 1012, 1013 and 1014 WebSocket close status code (#8664)

Motivation:

RFC 6455 doesn't define close status codes 1012, 1013 and 1014.
Yet, since then, IANA has defined them and web browsers support them.

From https://www.iana.org/assignments/websocket/websocket.xhtml:

* 1012: Service Restart
* 1013: Try Again Later
* 1014: The server was acting as a gateway or proxy and received an invalid response from the upstream server. This is similar to 502 HTTP Status Code.

Modification:

Make status codes 1012, 1013 and 1014 legit.

Result:

WebSocket status codes as defined by IANA are supported.
This commit is contained in:
Stephane Landelle 2018-12-17 19:42:50 +01:00 committed by Norman Maurer
parent de38d75137
commit 302dac8c45
2 changed files with 48 additions and 5 deletions

View File

@ -451,7 +451,7 @@ public class WebSocket08FrameDecoder extends ByteToMessageDecoder
// Must have 2 byte integer within the valid range
int statusCode = buffer.readShort();
if (statusCode >= 0 && statusCode <= 999 || statusCode >= 1004 && statusCode <= 1006
|| statusCode >= 1012 && statusCode <= 2999) {
|| statusCode >= 1015 && statusCode <= 2999) {
protocolViolation(ctx, "Invalid close frame getStatus code: " + statusCode);
}

View File

@ -12,18 +12,61 @@
*/
package io.netty.handler.codec.http.websocketx;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.embedded.EmbeddedChannel;
import org.junit.Test;
import org.mockito.Mockito;
import java.util.HashSet;
import java.util.Set;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
public class WebSocket08FrameDecoderTest {
@Test
public void channelInactive() throws Exception {
final WebSocket08FrameDecoder decoder = new WebSocket08FrameDecoder(true, true, 65535, false);
final ChannelHandlerContext ctx = Mockito.mock(ChannelHandlerContext.class);
final ChannelHandlerContext ctx = mock(ChannelHandlerContext.class);
decoder.channelInactive(ctx);
Mockito.verify(ctx).fireChannelInactive();
verify(ctx).fireChannelInactive();
}
@Test
public void supportIanaStatusCodes() throws Exception {
Set<Integer> forbiddenIanaCodes = new HashSet<Integer>();
forbiddenIanaCodes.add(1004);
forbiddenIanaCodes.add(1005);
forbiddenIanaCodes.add(1006);
Set<Integer> validIanaCodes = new HashSet<Integer>();
for (int i = 1000; i < 1015; i++) {
validIanaCodes.add(i);
}
validIanaCodes.removeAll(forbiddenIanaCodes);
for (int statusCode: validIanaCodes) {
EmbeddedChannel encoderChannel = new EmbeddedChannel(new WebSocket08FrameEncoder(true));
EmbeddedChannel decoderChannel = new EmbeddedChannel(new WebSocket08FrameDecoder(true, true, 65535, false));
assertTrue(encoderChannel.writeOutbound(new CloseWebSocketFrame(statusCode, "Bye")));
assertTrue(encoderChannel.finish());
ByteBuf serializedCloseFrame = encoderChannel.readOutbound();
assertNull(encoderChannel.readOutbound());
assertTrue(decoderChannel.writeInbound(serializedCloseFrame));
assertTrue(decoderChannel.finish());
CloseWebSocketFrame outputFrame = decoderChannel.readInbound();
assertNull(decoderChannel.readOutbound());
try {
assertEquals(statusCode, outputFrame.statusCode());
} finally {
outputFrame.release();
}
}
}
}