Http proxy in Netty websocket client to connect to internet

2.2k views Asked by At

My application is running behind a corporate firewall and I need to use http proxy(http://theclientproxy.net:8080) to connect to internet

I have used the Netty client as below, https://github.com/netty/netty/tree/4.1/example/src/main/java/io/netty/example/http/websocketx/client

Code:

    public final class WebSocketClient {

        static final String URL = System.getProperty("url", "wss://127.0.0.1:8080/websocket");

        public static void main(String[] args) throws Exception {
            URI uri = new URI(URL);
            String scheme = uri.getScheme() == null? "ws" : uri.getScheme();
            final String host = uri.getHost() == null? "127.0.0.1" : uri.getHost();
            final int port;
    final boolean ssl = "wss".equalsIgnoreCase(scheme);
            final SslContext sslCtx;
            if (ssl) {
                sslCtx = SslContextBuilder.forClient()
                    .trustManager(InsecureTrustManagerFactory.INSTANCE).build();
            } else {
                sslCtx = null;
            }


            EventLoopGroup group = new NioEventLoopGroup();
            try {
        final WebSocketClientHandler handler =
                            new WebSocketClientHandler(
                                    WebSocketClientHandshakerFactory.newHandshaker(
                                            uri, WebSocketVersion.V13, null, true, new DefaultHttpHeaders()));

                    Bootstrap b = new Bootstrap();
                    b.group(group)
                     .channel(NioSocketChannel.class)
                     .handler(new ChannelInitializer<SocketChannel>() {
                         @Override
                         protected void initChannel(SocketChannel ch) {
                             ChannelPipeline p = ch.pipeline();
                             if (sslCtx != null) {
                                 p.addFirst(new HttpProxyHandler(new InetSocketAddress("theclientproxy.net", 8080) ) );
                                 p.addLast(sslCtx.newHandler(ch.alloc(), host, port));
                             }
                             p.addLast(
                                     new HttpClientCodec(),
                                     new HttpObjectAggregator(8192),
                                     WebSocketClientCompressionHandler.INSTANCE,
                                     handler);
                         }
                     });

                    Channel ch = b.connect(uri.getHost(), port).sync().channel();
                    handler.handshakeFuture().sync();

BufferedReader console = new BufferedReader(new InputStreamReader(System.in));
            while (true) {
                String msg = console.readLine(); //THIS IS NULL IN DATA CENTER LOGS
                if (msg == null) {
                    break;
                } else if ("bye".equals(msg.toLowerCase())) {
                    ch.writeAndFlush(new CloseWebSocketFrame());
                    ch.closeFuture().sync();
                    break;
                } else if ("ping".equals(msg.toLowerCase())) {
                    WebSocketFrame frame = new PingWebSocketFrame(Unpooled.wrappedBuffer(new byte[] { 8, 1, 8, 1 }));
                    ch.writeAndFlush(frame);
                } else {
                    WebSocketFrame frame = new TextWebSocketFrame(msg);
                    ch.writeAndFlush(frame);
                }
            }
        } finally {
            group.shutdownGracefully();
        }

Handler:

public class WebSocketClientHandler extends SimpleChannelInboundHandler<Object> {

    private final WebSocketClientHandshaker handshaker;
    private ChannelPromise handshakeFuture;

    public WebSocketClientHandler(WebSocketClientHandshaker handshaker) {
        this.handshaker = handshaker;
    }

    public ChannelFuture handshakeFuture() {
        return handshakeFuture;
    }

    @Override
    public void handlerAdded(ChannelHandlerContext ctx) {
        handshakeFuture = ctx.newPromise();
    }

    @Override
    public void channelActive(ChannelHandlerContext ctx) {
        handshaker.handshake(ctx.channel());
    }

    @Override
    public void channelInactive(ChannelHandlerContext ctx) {
        System.out.println("WebSocket Client disconnected!");
    }

    @Override
    public void channelRead0(ChannelHandlerContext ctx, Object msg) throws Exception {
        Channel ch = ctx.channel();
        if (!handshaker.isHandshakeComplete()) {
            try {
                handshaker.finishHandshake(ch, (FullHttpResponse) msg);
                System.out.println("WebSocket Client connected!");
                handshakeFuture.setSuccess();
            } catch (WebSocketHandshakeException e) {
                System.out.println("WebSocket Client failed to connect");
                handshakeFuture.setFailure(e);
            }
            return;
        }

The application is able to connect to the websocket server endpoint from my local machine successfully.

But in the company datacenter where my application is deployed, I see the msg value is null and the websocket client is disconnected

Does that mean my connection is blocked at firewall? If that is the case then why did the statement "WebSocket Client connected!" is printed at all?

Thanks

1

There are 1 answers

0
firstpostcommenter On BEST ANSWER

The httpproxyhandler you used is correct

Just remove the BufferredReader code as mentioned below when deploying in linux, docker, etc: Netty WebSocket Client Channel always gets inactive on Linux Server