io.netty.handler.codec.compression.DecompressionException: GZIP header 中不支持的压缩方法 0
io.netty.handler.codec.compression.DecompressionException: Unsupported compression method 0 in the GZIP header
我实现了一个 netty 4 http 服务器。
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 管道工厂 class 是 -
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 是 -
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();
}
}
当我发送正常请求时,它工作正常。当我发送 gzip 压缩请求时出现错误 -
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.run(SingleThreadEventExecutor.java:989)
at io.netty.util.internal.ThreadExecutorMap.run(ThreadExecutorMap.java:74)
at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
at java.lang.Thread.run(Thread.java:748)
示例请求是 -
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���-!'
请求有效负载“�VP*I-.QR�R0T���-!”是使用以下逻辑对字符串 "{ \"test\" : 1 }"
进行 Gzip 压缩 -
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();
}
如何让Http解压在netty服务器上正常工作?
我测试http压缩的方式是错误的。下面的代码工作正常 -
try(CloseableHttpClient httpclient = HttpClients.createDefault()) {
HttpPost httppost = new HttpPost("http://localhost:5880/test");
String payload = "{ \"test\" : 1 }";
EntityBuilder builder = EntityBuilder.create().gzipCompress().setContentEncoding("gzip").chunked().setText(payload);
HttpEntity entity = builder.build();
httppost.setEntity(entity);
System.out.println();
httppost.setHeader("Accept-Encoding", "gzip,deflate");
httppost.setHeader("Content-Encoding", "gzip");
System.out.println("Executing request: " + httppost.getRequestLine());
CloseableHttpResponse response = httpclient.execute(httppost);
try {
System.out.println("----------------------------------------");
System.out.println(response.getStatusLine());
System.out.println(EntityUtils.toString(response.getEntity()));
} finally {
response.close();
}
}
我实现了一个 netty 4 http 服务器。
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 管道工厂 class 是 -
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 是 -
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();
}
}
当我发送正常请求时,它工作正常。当我发送 gzip 压缩请求时出现错误 -
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.run(SingleThreadEventExecutor.java:989) at io.netty.util.internal.ThreadExecutorMap.run(ThreadExecutorMap.java:74) at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30) at java.lang.Thread.run(Thread.java:748)
示例请求是 -
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���-!'
请求有效负载“�VP*I-.QR�R0T���-!”是使用以下逻辑对字符串 "{ \"test\" : 1 }"
进行 Gzip 压缩 -
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();
}
如何让Http解压在netty服务器上正常工作?
我测试http压缩的方式是错误的。下面的代码工作正常 -
try(CloseableHttpClient httpclient = HttpClients.createDefault()) {
HttpPost httppost = new HttpPost("http://localhost:5880/test");
String payload = "{ \"test\" : 1 }";
EntityBuilder builder = EntityBuilder.create().gzipCompress().setContentEncoding("gzip").chunked().setText(payload);
HttpEntity entity = builder.build();
httppost.setEntity(entity);
System.out.println();
httppost.setHeader("Accept-Encoding", "gzip,deflate");
httppost.setHeader("Content-Encoding", "gzip");
System.out.println("Executing request: " + httppost.getRequestLine());
CloseableHttpResponse response = httpclient.execute(httppost);
try {
System.out.println("----------------------------------------");
System.out.println(response.getStatusLine());
System.out.println(EntityUtils.toString(response.getEntity()));
} finally {
response.close();
}
}