Netty websocket and Rest in same Java application

回眸只為那壹抹淺笑 提交于 2021-01-28 12:25:36

问题


I have an exisiting Java application which is exposing REST services. I want to add a new feature in the same application to handle web socket requests (using netty) along with the exisiting REST services. How can I do that without changing my REST services?


回答1:


There are two ways to do this without changing your REST service:

  1. I would suggest you setup a normal netty websocket server and run it parallel on another port (this can happen in the same application).

  2. A more complicated an inefficient solution would be to write a netty http/websocket server which runs on the default port (80/443) and sends all REST requests to your REST service. So basically you would write a sort of HTTP proxy which also hosts the websocket server (could also happen in the same application).

Here is an example of how to write a netty websocket server.




回答2:


You can use a handler before the handler that receives http requests. The basic task of this handler would be to see if the http request contains WebSocket upgrade headers. If that is the case it would complete the handshake and continue to handle the websocket frames otherwise it will pass the http requests to the next handler as follows:

import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.handler.codec.http.HttpHeaderNames;
import io.netty.handler.codec.http.HttpHeaderValues;
import io.netty.handler.codec.http.HttpHeaders;
import io.netty.handler.codec.http.HttpMethod;
import io.netty.handler.codec.http.HttpRequest;
import io.netty.handler.codec.http.websocketx.WebSocketFrame;
import io.netty.handler.codec.http.websocketx.WebSocketServerHandshaker;
import io.netty.handler.codec.http.websocketx.WebSocketServerHandshakerFactory;

public class WebSocketServerHandler extends ChannelInboundHandlerAdapter {
    private WebSocketServerHandshaker handshaker;

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) {
        if (msg instanceof HttpRequest) {
            HttpRequest httpRequest = (HttpRequest) msg;
            HttpMethod requestMethod = httpRequest.method();

            if (containsUpgradeHeaders(httpRequest)) {
                if (HttpMethod.GET == requestMethod) {
                    // Handshake
                    WebSocketServerHandshakerFactory wsFactory = new WebSocketServerHandshakerFactory(
                            getWebSocketLocation(httpRequest), null, false, Integer.MAX_VALUE);
                    handshaker = wsFactory.newHandshaker(httpRequest);
                    if (handshaker == null) {
                        WebSocketServerHandshakerFactory.sendUnsupportedVersionResponse(ctx.channel());
                    } else {
                        handshaker.handshake(ctx.channel(), httpRequest);
                    }

                }
            } else {
                //Let the http handler handle the request
                ctx.fireChannelRead(msg);
            }

        } else if (msg instanceof WebSocketFrame) {
            handleWebSocketFrame(ctx, (WebSocketFrame) msg);
        } else {
            throw new IllegalStateException("unknown message: " + msg);
        }
    }

    private boolean containsUpgradeHeaders(HttpRequest httpRequest) {
        HttpHeaders headers = httpRequest.headers();
        return headers.containsValue(HttpHeaderNames.CONNECTION, HttpHeaderValues.UPGRADE, true) && headers
                .containsValue(HttpHeaderNames.UPGRADE, HttpHeaderValues.WEBSOCKET, true);
    }

    private static String getWebSocketLocation(HttpRequest req) {
        return "ws://" + req.headers().get(HttpHeaderNames.HOST);
    }

    private void handleWebSocketFrame(ChannelHandlerContext ctx, WebSocketFrame frame) {
        //handle the websocket frame
    }
}

Or you may use a different handler to handle the websocket frames by replacing the http request handler with a WebSocket frames handler once the handshake is completed.



来源:https://stackoverflow.com/questions/52759267/netty-websocket-and-rest-in-same-java-application

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!