Search code examples
javahttpnettychunked-encoding

Get the number of received bytes in Netty for gzip chunked response


I'm trying to solve a problem in a description. Currently I have this pipeline:

p.addLast(sslCtx.newHandler(ch.alloc()));
p.addLast(new HttpClientCodec());
p.addLast(new MyCustomHttpContentDecompressor());
// p.addLast(new HttpObjectAggregator(1048576));
p.addLast(businessLogicHandler);

When server returns non chunked response, it contains Content-Length header. I succeeded to retrieve this value in my custom HttpContentDecompressor just before it removes this header and performs gzip decompression.

But when server decides to send chunked response, I'm out of luck since there's no Content-Length header. I tried HttpObjectAggregator but seems that it returns the number of decompressed bytes. I also reviewed netty traffic package, but it solves a different task.

I feel that solution is simple, but I do not know netty well. Maybe there's a way to add one more handler to pipeline (ex. before decompressor), that will read all bytes in buffer, save the number and pass them further to pipeline? Some code examples will be very helpful.


Solution

  • Solution:

    public class TrafficInterceptorHandler extends ChannelInboundHandlerAdapter {
    
        public static final String NAME = "trafficInterceptor";
        private static Logger LOG = LoggerFactory.getLogger(TrafficInterceptorHandler.class);
    
        private AtomicInteger readBytes = new AtomicInteger(0);
    
        @Override
        public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
            if (msg instanceof ByteBuf) {
                ByteBuf byteBuf = (ByteBuf) msg;
                readBytes.addAndGet(byteBuf.readableBytes());
            } else {
                LOG.warn("Received msg is not a ByteBuffer. Actual class: " + msg.getClass());
            }
            ctx.fireChannelRead(msg);
        }
        public int getReadBytes() {
            return readBytes.get();
        }
    }
    

    Should be added to pipeline before other handlers

    p.addLast(TrafficInterceptorHandler.NAME, new TrafficInterceptorHandler());
    p.addLast(sslCtx.newHandler(ch.alloc()));
    p.addLast(new HttpClientCodec());
    ...