Skip to content

Instantly share code, notes, and snippets.

@danbev
Created July 24, 2012 14:05
Show Gist options
  • Save danbev/3170072 to your computer and use it in GitHub Desktop.
Save danbev/3170072 to your computer and use it in GitHub Desktop.
Netty 4 WebSocket suggestion

Suggestion for Netty 4 WebSockets

This document is intended to explain a suggestion for an enhancement of the WebSocket support in Netty 4 and was only created to get feedback from the Netty team to see if this is a valid suggestion before putting any time and effort into it.

Netty has a very nice support for WebSockets and the examples provided work like a charm. This is one of the examples that come with Netty WebSocketServerHandler.java. In this example the WebSocketServerHandler takes care of everything in regard to the WebSocket request, and also acts as a simple web server to produce the html page used for running the example using a web browser.

The reason for this suggestion is that I wanted to implement a simple handler that receives a TextWebSocketFrame and not have to deal with other things like the Http Handshake.So I've created the following branch to show what I'm after.

To start with I'd like to show what a Netty server looks like in this case:

    public static void main(String[] args) throws Exception {
        final ServerBootstrap sb = new ServerBootstrap();
        try {
            sb.eventLoop(new NioEventLoop(), new NioEventLoop())
             .channel(new NioServerSocketChannel())
             .localAddress(new InetSocketAddress(8080))
             .childHandler(new ChannelInitializer<SocketChannel>() {
                @Override
                public void initChannel(final SocketChannel ch) throws Exception {
                    ch.pipeline().addLast(new HttpRequestDecoder(),
                        new HttpChunkAggregator(65536),
                        new HttpResponseEncoder(),
                        new WebSocketHandshakeHandler("/websocket"),
                        new WebSocketProtocolHandler(), 
                        new CustomTextFrameHandler());
                }
            });

            final Channel ch = sb.bind().sync().channel();
            System.out.println("Web socket server started at port 8080");

            ch.closeFuture().sync();
        } finally {
            sb.shutdown();
        }
    }

Where CustomTextFrameHandler would look something like this:

    public class CustomTextFrameHandler extends ChannelInboundMessageHandlerAdapter<TextWebSocketFrame> {
    
        @Override
        public void messageReceived(ChannelHandlerContext ctx, TextWebSocketFrame frame) throws Exception {
            String request = ((TextWebSocketFrame) frame).getText();
            ctx.channel().write(new TextWebSocketFrame(request.toUpperCase()));
        }
    
        @Override
        public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
            cause.printStackTrace();
            ctx.close();
        }
    }

The code in messageReceived is from the original WebSocket example mentioned above. What is different is that there are two more handlers in the pipeline:

  1. WebSocketHandshakeHandler.java

    This handler takes care of the HTTP Upgrade request and after a successful handshake will remove itself from the pipeline.

  2. WebSocketProtocolHandler.java

    This handler takes care of the WebSocket protocol by handling close, and ping requests. All other requests will be passed along to the next inbound handler in the chain.

@trustin
Copy link

trustin commented Jul 25, 2012

WebSocketProtocolHandler could insert WebSocketHandshakeHandler right before itself when it's added, then we could hide WebSocketHandshakeHandler completely (package private) unless there's a good use case to use it separately. I also would love to see some additional methods like WebSocketProtocolHandler.handleNonWebSocketRequest(HttpRequest) whose default implementation is to respond with 403. WDYT?

@danbev
Copy link
Author

danbev commented Jul 25, 2012

WebSocketProtocolHandler could insert WebSocketHandshakeHandler right before itself when it's added, then we could hide WebSocketHandshakeHandler completely (package private)
Ah, good idea. I did not think about having the WebSocketHandshakeHandler add the WebSocketProtocolHandler. Let me take a stab at this and see what you think.

I also would love to see some additional methods like WebSocketProtocolHandler.handleNonWebSocketRequest(HttpRequest) whose default implementation is to respond with 403.
Sounds great, I'll add this and some tests to cover this, and add some additional tests for situations which are currently not covered.

Thanks!

@trustin
Copy link

trustin commented Jul 26, 2012

Awesome. Let me look forward to your update. :-)

@danbev
Copy link
Author

danbev commented Jul 26, 2012

I've made some changes now...

  1. WebSocketProtocolHandler now adds the WebSocketHandshakeHandler which has been made private.
  2. Not sure if this was what you had in mind for the 403 issue, if not, then let me know and I'll have another go at it. This is the accompanying test.

@danbev
Copy link
Author

danbev commented Aug 17, 2012

Hey Trustin,

did you get a chance to have a look at these suggestions?

Thanks

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment