NETTY-383 deflate-raw support for HttpContentDecompressor
* Added ZlibWrapperType.ZLIB_OR_NONE for auto-detection and updated the relevant Zlib implementation
This commit is contained in:
parent
0859ff782e
commit
8763c0b858
@ -125,25 +125,32 @@ public class ZlibDecoder extends OneToOneDecoder {
|
||||
z.next_out_index = 0;
|
||||
z.avail_out = out.length;
|
||||
|
||||
do {
|
||||
|
||||
loop: for (;;) {
|
||||
// Decompress 'in' into 'out'
|
||||
int resultCode = z.inflate(JZlib.Z_SYNC_FLUSH);
|
||||
if (z.next_out_index > 0) {
|
||||
decompressed.writeBytes(out, 0, z.next_out_index);
|
||||
z.avail_out = out.length;
|
||||
}
|
||||
z.next_out_index = 0;
|
||||
|
||||
switch (resultCode) {
|
||||
case JZlib.Z_STREAM_END:
|
||||
finished = true; // Do not decode anymore.
|
||||
z.inflateEnd();
|
||||
break loop;
|
||||
case JZlib.Z_OK:
|
||||
break;
|
||||
case JZlib.Z_BUF_ERROR:
|
||||
decompressed.writeBytes(out, 0, z.next_out_index);
|
||||
z.next_out_index = 0;
|
||||
z.avail_out = out.length;
|
||||
if (resultCode == JZlib.Z_STREAM_END) {
|
||||
finished = true; // Do not decode anymore.
|
||||
z.inflateEnd();
|
||||
if (z.avail_in <= 0) {
|
||||
break loop;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
ZlibUtil.fail(z, "decompression failure", resultCode);
|
||||
}
|
||||
} while (z.avail_in > 0);
|
||||
}
|
||||
|
||||
if (decompressed.writerIndex() != 0) { // readerIndex is always 0
|
||||
return decompressed;
|
||||
|
@ -104,6 +104,11 @@ public class ZlibEncoder extends OneToOneEncoder implements LifeCycleAwareChanne
|
||||
if (wrapper == null) {
|
||||
throw new NullPointerException("wrapper");
|
||||
}
|
||||
if (wrapper == ZlibWrapper.ZLIB_OR_NONE) {
|
||||
throw new IllegalArgumentException(
|
||||
"wrapper '" + ZlibWrapper.ZLIB_OR_NONE + "' is not " +
|
||||
"allowed for compression.");
|
||||
}
|
||||
|
||||
synchronized (z) {
|
||||
int resultCode = z.deflateInit(compressionLevel, ZlibUtil.convertWrapperType(wrapper));
|
||||
|
@ -48,6 +48,9 @@ final class ZlibUtil {
|
||||
case GZIP:
|
||||
convertedWrapperType = JZlib.W_GZIP;
|
||||
break;
|
||||
case ZLIB_OR_NONE:
|
||||
convertedWrapperType = JZlib.W_ZLIB_OR_NONE;
|
||||
break;
|
||||
default:
|
||||
throw new Error();
|
||||
}
|
||||
|
@ -35,5 +35,10 @@ public enum ZlibWrapper {
|
||||
/**
|
||||
* Raw DEFLATE stream only (no header and no footer).
|
||||
*/
|
||||
NONE;
|
||||
NONE,
|
||||
/**
|
||||
* Try {@link #ZLIB} first and then {@link #NONE} if the first attempt fails.
|
||||
* Please note that you can specify this wrapper type only when decompressing.
|
||||
*/
|
||||
ZLIB_OR_NONE;
|
||||
}
|
||||
|
@ -35,7 +35,8 @@ public class HttpContentDecompressor extends HttpContentDecoder {
|
||||
if ("gzip".equalsIgnoreCase(contentEncoding) || "x-gzip".equalsIgnoreCase(contentEncoding)) {
|
||||
return new DecoderEmbedder<ChannelBuffer>(new ZlibDecoder(ZlibWrapper.GZIP));
|
||||
} else if ("deflate".equalsIgnoreCase(contentEncoding) || "x-deflate".equalsIgnoreCase(contentEncoding)) {
|
||||
return new DecoderEmbedder<ChannelBuffer>(new ZlibDecoder(ZlibWrapper.ZLIB));
|
||||
// To be strict, 'deflate' means ZLIB, but some servers were not implemented correctly.
|
||||
return new DecoderEmbedder<ChannelBuffer>(new ZlibDecoder(ZlibWrapper.ZLIB_OR_NONE));
|
||||
}
|
||||
|
||||
// 'identity' or unsupported
|
||||
|
@ -1306,6 +1306,11 @@ final class Deflate {
|
||||
|
||||
private int deflateInit2(ZStream strm, int level, int method, int windowBits,
|
||||
int memLevel, int strategy, WrapperType wrapperType) {
|
||||
|
||||
if (wrapperType == WrapperType.ZLIB_OR_NONE) {
|
||||
throw new IllegalArgumentException("ZLIB_OR_NONE allowed only for inflate");
|
||||
}
|
||||
|
||||
// byte[] my_version=ZLIB_VERSION;
|
||||
|
||||
//
|
||||
|
@ -111,6 +111,7 @@ final class Inflate {
|
||||
z.istate.mode = BLOCKS;
|
||||
break;
|
||||
case ZLIB:
|
||||
case ZLIB_OR_NONE:
|
||||
z.istate.mode = METHOD;
|
||||
break;
|
||||
case GZIP:
|
||||
@ -174,6 +175,19 @@ final class Inflate {
|
||||
if (z.avail_in == 0) {
|
||||
return r;
|
||||
}
|
||||
|
||||
// Switch from zlib to none if necessary.
|
||||
if (z.istate.wrapperType == WrapperType.ZLIB_OR_NONE) {
|
||||
if ((z.next_in[z.next_in_index] & 0xf) != JZlib.Z_DEFLATED ||
|
||||
(z.next_in[z.next_in_index] >> 4) + 8 > z.istate.wbits) {
|
||||
z.istate.wrapperType = WrapperType.NONE;
|
||||
z.istate.mode = BLOCKS;
|
||||
break;
|
||||
} else {
|
||||
z.istate.wrapperType = WrapperType.ZLIB;
|
||||
}
|
||||
}
|
||||
|
||||
r = f;
|
||||
|
||||
z.avail_in --;
|
||||
@ -286,17 +300,23 @@ final class Inflate {
|
||||
gzipUncompressedBytes += decompressedBytes;
|
||||
z.crc32 = CRC32.crc32(z.crc32, z.next_out, old_next_out_index, decompressedBytes);
|
||||
}
|
||||
|
||||
if (z.istate.wrapperType == WrapperType.NONE) {
|
||||
z.istate.mode = DONE;
|
||||
break;
|
||||
} else if (z.istate.wrapperType == WrapperType.ZLIB) {
|
||||
z.istate.mode = CHECK4;
|
||||
} else {
|
||||
} else if (z.istate.wrapperType == WrapperType.GZIP){
|
||||
gzipCRC32 = 0;
|
||||
gzipISize = 0;
|
||||
gzipBytesToRead = 4;
|
||||
z.istate.mode = GZIP_CRC32;
|
||||
break;
|
||||
} else {
|
||||
z.istate.mode = BAD;
|
||||
z.msg = "unexpected state";
|
||||
z.istate.marker = 0;
|
||||
break;
|
||||
}
|
||||
case CHECK4:
|
||||
if (z.avail_in == 0) {
|
||||
|
@ -54,6 +54,7 @@ public final class JZlib {
|
||||
public static final Enum<?> W_NONE = WrapperType.NONE;
|
||||
public static final Enum<?> W_ZLIB = WrapperType.ZLIB;
|
||||
public static final Enum<?> W_GZIP = WrapperType.GZIP;
|
||||
public static final Enum<?> W_ZLIB_OR_NONE = WrapperType.ZLIB_OR_NONE;
|
||||
|
||||
// compression levels
|
||||
public static final int Z_NO_COMPRESSION = 0;
|
||||
@ -103,6 +104,6 @@ public final class JZlib {
|
||||
static final int MAX_BL_BITS = 7;
|
||||
|
||||
static enum WrapperType {
|
||||
NONE, ZLIB, GZIP;
|
||||
NONE, ZLIB, GZIP, ZLIB_OR_NONE;
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user