private void handleHttpRequest(ChannelHandlerContext ctx, FullHttpRequest req) throws Exception {
        // Handle a bad request.
        if (!req.getDecoderResult().isSuccess()) {
            sendHttpResponse(ctx, req, new DefaultFullHttpResponse(HTTP_1_1, BAD_REQUEST));
            return;
        }

        // Allow only GET methods.
        if (req.getMethod() != GET) {
            sendHttpResponse(ctx, req, new DefaultFullHttpResponse(HTTP_1_1, FORBIDDEN));
            return;
        }

        // Send the demo page and favicon.ico
        if ("/favicon.ico".equals(req.getUri())) {
            FullHttpResponse res = new DefaultFullHttpResponse(HTTP_1_1, NOT_FOUND);
            sendHttpResponse(ctx, req, res);
            return;
        } else if ("/hexdump.js".equals(req.getUri())) {
            final WebSocketServerJSPage webSocketServerJSPage = new WebSocketServerJSPage();
            ByteBuf content = webSocketServerJSPage.getContent(getWebSocketLocation(req));
            sendHttpResponse(ctx, req, content, "text/javascript; charset=UTF-8");
            return;
        } else if ("/".equals(req.getUri())) {
            WebSocketServerIndexPage webSocketServerIndexPage = new WebSocketServerIndexPage();
            ByteBuf content = webSocketServerIndexPage.getContent(getWebSocketLocation(req));
            sendHttpResponse(ctx, req, content, "text/html; charset=UTF-8");
            return;
        }

        // Handshake
        WebSocketServerHandshakerFactory wsFactory = new WebSocketServerHandshakerFactory(
                getWebSocketLocation(req), null, false);
        handshaker = wsFactory.newHandshaker(req);
        if (handshaker == null) {
            WebSocketServerHandshakerFactory.sendUnsupportedWebSocketVersionResponse(ctx.channel());
            return;
        } 
        
        try {
            handshaker.handshake(ctx.channel(), req);
        } catch (Exception e) {
            logger.log(Level.WARNING, "websocket handshake failed", e);
            WebSocketServerHandshakerFactory.sendUnsupportedWebSocketVersionResponse(ctx.channel());
            return;
        }
        zkStateObserver.addListener(new OutboundConnector(ctx));
    }