Support 1012, 1013 and 1014 WebSocket status code

Motivation:

RFC 6455 doesn't define status codes 1012, 1013 and 1014.
Yet, since then, IANA has defined them, web browsers support them, applications in the wild do use them but it's currently not possible to buid a Netty based client for those services.

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-14 10:27:37 +01:00
parent 83ab4ef5e3
commit db6d94f82a
2 changed files with 56 additions and 1 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,11 +12,20 @@
*/
package io.netty.handler.codec.http.websocketx;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.UnpooledByteBufAllocator;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import org.junit.Test;
import static org.junit.Assert.*;
import org.mockito.Mockito;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
public class WebSocket08FrameDecoderTest {
@Test
@ -26,4 +35,50 @@ public class WebSocket08FrameDecoderTest {
decoder.channelInactive(ctx);
Mockito.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);
ChannelHandlerContext ctx = Mockito.mock(ChannelHandlerContext.class);
Mockito.when(ctx.alloc()).thenReturn(UnpooledByteBufAllocator.DEFAULT);
Channel channel = Mockito.mock(Channel.class);
Mockito.when(channel.isActive()).thenReturn(false);
Mockito.when(ctx.channel()).thenReturn(channel);
List<Object> out = new ArrayList<Object>();
for (int statusCode: validIanaCodes) {
WebSocket08FrameEncoder encoder = new WebSocket08FrameEncoder(true);
WebSocket08FrameDecoder decoder = new WebSocket08FrameDecoder(true, true, 65535, false);
CloseWebSocketFrame inputFrame = new CloseWebSocketFrame(statusCode, "Bye");
try {
encoder.encode(ctx, inputFrame, out);
ByteBuf serializedCloseFrame = (ByteBuf) out.get(0);
out.clear();
decoder.decode(ctx, serializedCloseFrame, out);
CloseWebSocketFrame outputFrame = (CloseWebSocketFrame) out.get(0);
out.clear();
try {
assertEquals(statusCode, outputFrame.statusCode());
} finally {
outputFrame.release();
}
} finally {
inputFrame.release();
}
}
}
}