question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

io.netty.handler.codec.compression.DecompressionException: Unsupported compression method 0 in the GZIP header

See original GitHub issue

Expected behavior

I’m expecting HttpDecompressor to decompress the payload correctly when the request payload is compresssed with gzip.

Actual behavior

I’m getting the below exception -

io.netty.handler.codec.compression.DecompressionException: Unsupported compression method 0 in the GZIP header at io.netty.handler.codec.compression.JdkZlibDecoder.readGZIPHeader(JdkZlibDecoder.java:321) at io.netty.handler.codec.compression.JdkZlibDecoder.decode(JdkZlibDecoder.java:212) at io.netty.handler.codec.ByteToMessageDecoder.decodeRemovalReentryProtection(ByteToMessageDecoder.java:498) at io.netty.handler.codec.ByteToMessageDecoder.callDecode(ByteToMessageDecoder.java:437) at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:276) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365) at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357) at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1410) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365) at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:919) at io.netty.channel.embedded.EmbeddedChannel.writeInbound(EmbeddedChannel.java:343) at io.netty.handler.codec.http.HttpContentDecoder.decode(HttpContentDecoder.java:254) at io.netty.handler.codec.http.HttpContentDecoder.decodeContent(HttpContentDecoder.java:161) at io.netty.handler.codec.http.HttpContentDecoder.decode(HttpContentDecoder.java:150) at io.netty.handler.codec.http.HttpContentDecoder.decode(HttpContentDecoder.java:47) at io.netty.handler.codec.MessageToMessageDecoder.channelRead(MessageToMessageDecoder.java:88) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365) at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357) at io.netty.handler.codec.MessageToMessageDecoder.channelRead(MessageToMessageDecoder.java:102) at io.netty.handler.codec.MessageToMessageCodec.channelRead(MessageToMessageCodec.java:111) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365) at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357) at io.netty.channel.CombinedChannelDuplexHandler$DelegatingChannelHandlerContext.fireChannelRead(CombinedChannelDuplexHandler.java:436) at io.netty.handler.codec.ByteToMessageDecoder.fireChannelRead(ByteToMessageDecoder.java:321) at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:295) at io.netty.channel.CombinedChannelDuplexHandler.channelRead(CombinedChannelDuplexHandler.java:251) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365) at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357) at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1410) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365) at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:919) at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:163) at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:714) at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:650) at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:576) at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:493) at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:989) at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74) at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30) at java.lang.Thread.run(Thread.java:748)

Steps to reproduce

    curl --location --request POST 'http://localhost:5880/' \
    --header 'Content-Type: application/json' \
    --header 'Accept: */*' \
    --header 'Accept-Encoding: gzip' \
    --header 'Accept-Language: en-US,en;q=0.9' \
    --header 'Connection: Keep-Alive' \
    --header 'Content-Encoding: gzip' \
    --header 'Content-Type: text/plain' \
    --data-raw '�VP*I-.QR�R0T���-!'

The request payload ‘�VP*I-.QR�R0T���-!’ is Gzip compression of string "{ \"test\" : 1 }" using below logic -

     public static byte[] compress(String str) throws Exception {
        if (str == null || str.length() == 0) {
            return null;
        }
        System.out.println("String length : " + str.length());
        ByteArrayOutputStream obj=new ByteArrayOutputStream();
        GZIPOutputStream gzip = new GZIPOutputStream(obj, 2);
        gzip.write(str.getBytes("UTF-8"));
        gzip.close();

        return obj.toByteArray();
    }

Minimal yet complete reproducer code (or URL to code)

    public void start() {
        System.out.println("In Start method");
        try {
            ServerBootstrap b = new ServerBootstrap();
            EventLoopGroup bossGroup = new NioEventLoopGroup();
            EventLoopGroup workerGroup = new NioEventLoopGroup();

            b.group(bossGroup, workerGroup)
                    .channel(NioServerSocketChannel.class)
                    .childHandler(new HttpServerPipelineFactory())
                    .option(ChannelOption.SO_BACKLOG, 128)
                    .childOption(ChannelOption.WRITE_BUFFER_WATER_MARK, WriteBufferWaterMark.DEFAULT)
                    .childOption(ChannelOption.AUTO_READ, false)
                    .childOption(ChannelOption.SO_KEEPALIVE, true);

            ChannelFuture f = b.bind(listenerPort).sync();
            System.out.println("server started listening on port " + listenerPort);
            f.channel().closeFuture().sync();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

HTTP pipeline factory class is -

    public class HttpServerPipelineFactory extends ChannelInitializer<Channel> {

        @Override
        protected void initChannel(Channel ch) {
            ChannelPipeline pipeline = ch.pipeline();
            pipeline.addLast("codec", new HttpServerCodec());
            pipeline.addLast("compress", new HttpContentCompressor());
            pipeline.addLast("decompress", new HttpContentDecompressor());
            pipeline.addLast("aggregator", new HttpObjectAggregator( 512 * 1024));
            pipeline.addLast("chunked", new ChunkedWriteHandler());
            pipeline.addLast("flow", new FlowControlHandler());
            pipeline.addLast("keep-alive", new HttpServerKeepAliveHandler());
            pipeline.addLast("request", new HTTPRequestHandler());
        }
    }

HTTPRequestHandler is -

    import static io.netty.handler.codec.http.HttpHeaderNames.CONTENT_LENGTH;
    import static io.netty.handler.codec.http.HttpResponseStatus.OK;
    import static io.netty.handler.codec.http.HttpVersion.HTTP_1_1;
    import static io.netty.util.CharsetUtil.UTF_8;

    public class HTTPRequestHandler extends SimpleChannelInboundHandler<FullHttpRequest> {

        private static Logger logger = LoggerFactory.getLogger(HTTPRequestHandler.class);

        @Override
        protected void channelRead0(ChannelHandlerContext ctx, FullHttpRequest request) {
            System.out.println("uri is " + request.uri());
            String responseStr = request.method() +"/ Got request at " + request.uri();
            System.out.println("body is \n" + request.content().toString(UTF_8));
            FullHttpResponse response = new DefaultFullHttpResponse(HTTP_1_1, OK, Unpooled.copiedBuffer(responseStr.getBytes()), false);
            response.headers().set(CONTENT_LENGTH, response.content().readableBytes());
            ctx.channel().writeAndFlush(response);
            ctx.read();
        }

        @Override
        public void channelActive(ChannelHandlerContext ctx) throws Exception {
            super.channelActive(ctx);
            ctx.read();
        }
    }

Netty version

4.1.14.Final

JVM version (e.g. java -version)

openjdk version "1.8.0_232"

OS version (e.g. uname -a)

Darwin BOSM0001-RANATA.local 16.7.0 Darwin Kernel Version 16.7.0: Sun Jun  2 20:26:31 PDT 2019; root:xnu-3789.73.50~1/RELEASE_X86_64 x86_64

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Comments:8 (5 by maintainers)

github_iconTop GitHub Comments

1reaction
hyperxprocommented, Apr 6, 2020

Replace compressedData byte array with your compressed data byte array.

0reactions
slandellecommented, Apr 6, 2020

This won’t work, see #2132.

HttpContentDecompressor extends HttpContentDecoder that currently only decodes HttpRequests and HttpContentCompressor extends HttpContentEncoder that currently only encodes HttpResponses.

In short: Netty only supports compressing server side and decompressing client side, not the other way around like you’re trying to do.

Read more comments on GitHub >

github_iconTop Results From Across the Web

io.netty.handler.codec.compression.DecompressionException
The way I'm testing the http compression is wrong. Below code works fine - try(CloseableHttpClient httpclient = HttpClients.
Read more >
com.couchbase.client.deps.io.netty.handler.codec ... - Tabnine
Validates that the offset extracted from a compressed reference is within * the permissible bounds of an offset (4 <= offset <= 32768), ......
Read more >
io.netty.handler.codec.compression.JdkZlibDecoder - Netty 4.0.56 ...
以上源码来自: 即时通讯网 - 即时通讯开发者社区!
Read more >
JdkZlibDecoder xref - Netty
15 */ 16 package io.netty.handler.codec.compression; 17 18 import io.netty.buffer. ... 43 44 private enum GzipState { 45 HEADER_START, 46 HEADER_END, ...
Read more >
io.netty.handler.codec.compression.JdkZlibDecoder.java ...
Here is the source code for io.netty.handler.codec.compression.JdkZlibDecoder.java ... "Unsupported compression method " + method + " in the GZIP header"); ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found