Crystark
Crystark

Reputation: 4246

Netty filtering reverse proxy

I'm trying to code a high performance reverse proxy server using Netty 4.1. I based my code on an Java adaptation of Feng-Zihao/protox and the Netty Proxy Example.

I first had some trouble handling 100-CONTINUE but adding the HttpObjectAggregator into my pipeline kinda solved that.

    serverBootstrap
        .group(bossGroup, workerGroup)
        .channel(NioServerSocketChannel.class)
        .handler(new LoggingHandler(LogLevel.DEBUG))
        .childHandler(new ChannelInitializer<SocketChannel>() {
            @Override
            public void initChannel(SocketChannel ch) throws Exception {
                ch.pipeline().addLast(new LoggingHandler(LogLevel.DEBUG));
                ch.pipeline().addLast(new HttpRequestDecoder());
                ch.pipeline().addLast(new HttpResponseEncoder());
                ch.pipeline().addLast(new HttpObjectAggregator(1048576));
                ch.pipeline().addLast(new FrontendHandler());
            }
        })
        //          .option(ChannelOption.SO_REUSEADDR, true)
        //          .option(ChannelOption.SO_BACKLOG, 128)
        //          .childOption(ChannelOption.SO_KEEPALIVE, true)
        .childOption(ChannelOption.AUTO_READ, false)
        .bind(port).sync();

On the client side, the request hangs indefinitely. The thing is, AUTO_READ being at false seems to prevent the HttpObjectAggregator to do his work and my FrontendHandler only ever receives the channelActive event but never the channelRead.

It seems though that I need that to make sure I don't get into some race condition between the reads and the remote peer connection.

FYI, my goal in the end is to choose to forward or not the request based on a filter (probably a new handler right before my FrontendHandler) that will need to read the full http content.

Am I missing something here ?

Upvotes: 3

Views: 1762

Answers (1)

Chris O&#39;Toole
Chris O&#39;Toole

Reputation: 1281

Turn on auto read when your outbound channel becomes active, and have your FrontendHandler turn it off while processing each message. Then turn it on again when you are ready to handle another message.

This will let HttpObjectAggregator keep reading as many messages as it needs to in order to create a FullHttpMessage, and then stop sending it messages while your FrontendHandler is processing or waiting on some client write to invoke a listener.

public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
    ctx.channel().config().setAutoRead(false);
    ...
    // This call should probably be in some event listener
    ctx.channel().config().setAutoRead(true);

Upvotes: 3

Related Questions