1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package io.netty.handler.codec.http;
17
18 import io.netty.channel.Channel;
19 import io.netty.channel.embedded.EmbeddedChannel;
20 import io.netty.handler.codec.compression.Brotli;
21 import io.netty.handler.codec.compression.BrotliDecoder;
22 import io.netty.handler.codec.compression.SnappyFrameDecoder;
23 import io.netty.handler.codec.compression.ZlibCodecFactory;
24 import io.netty.handler.codec.compression.ZlibWrapper;
25 import io.netty.handler.codec.compression.Zstd;
26 import io.netty.handler.codec.compression.ZstdDecoder;
27
28 import static io.netty.handler.codec.http.HttpHeaderValues.BR;
29 import static io.netty.handler.codec.http.HttpHeaderValues.DEFLATE;
30 import static io.netty.handler.codec.http.HttpHeaderValues.GZIP;
31 import static io.netty.handler.codec.http.HttpHeaderValues.SNAPPY;
32 import static io.netty.handler.codec.http.HttpHeaderValues.X_DEFLATE;
33 import static io.netty.handler.codec.http.HttpHeaderValues.X_GZIP;
34 import static io.netty.handler.codec.http.HttpHeaderValues.ZSTD;
35 import static io.netty.util.internal.ObjectUtil.checkPositiveOrZero;
36
37
38
39
40
41
42 public class HttpContentDecompressor extends HttpContentDecoder {
43
44 private final boolean strict;
45 private final int maxAllocation;
46
47
48
49
50
51
52 @Deprecated
53 public HttpContentDecompressor() {
54 this(false, 0);
55 }
56
57
58
59
60
61
62 public HttpContentDecompressor(int maxAllocation) {
63 this(false, maxAllocation);
64 }
65
66
67
68
69
70
71
72
73
74 @Deprecated
75 public HttpContentDecompressor(boolean strict) {
76 this(strict, 0);
77 }
78
79
80
81
82
83
84
85
86
87 public HttpContentDecompressor(boolean strict, int maxAllocation) {
88 this.strict = strict;
89 this.maxAllocation = checkPositiveOrZero(maxAllocation, "maxAllocation");
90 }
91
92 @Override
93 protected EmbeddedChannel newContentDecoder(String contentEncoding) throws Exception {
94 Channel channel = ctx.channel();
95 if (GZIP.contentEqualsIgnoreCase(contentEncoding) ||
96 X_GZIP.contentEqualsIgnoreCase(contentEncoding)) {
97 return EmbeddedChannel.builder()
98 .channelId(channel.id())
99 .hasDisconnect(channel.metadata().hasDisconnect())
100 .config(channel.config())
101 .handlers(ZlibCodecFactory.newZlibDecoder(ZlibWrapper.GZIP, maxAllocation))
102 .build();
103 }
104 if (DEFLATE.contentEqualsIgnoreCase(contentEncoding) ||
105 X_DEFLATE.contentEqualsIgnoreCase(contentEncoding)) {
106 final ZlibWrapper wrapper = strict ? ZlibWrapper.ZLIB : ZlibWrapper.ZLIB_OR_NONE;
107
108 return EmbeddedChannel.builder()
109 .channelId(channel.id())
110 .hasDisconnect(channel.metadata().hasDisconnect())
111 .config(channel.config())
112 .handlers(ZlibCodecFactory.newZlibDecoder(wrapper, maxAllocation))
113 .build();
114 }
115 if (Brotli.isAvailable() && BR.contentEqualsIgnoreCase(contentEncoding)) {
116 return EmbeddedChannel.builder()
117 .channelId(channel.id())
118 .hasDisconnect(channel.metadata().hasDisconnect())
119 .config(channel.config())
120 .handlers(new BrotliDecoder())
121 .build();
122 }
123
124 if (SNAPPY.contentEqualsIgnoreCase(contentEncoding)) {
125 return EmbeddedChannel.builder()
126 .channelId(channel.id())
127 .hasDisconnect(channel.metadata().hasDisconnect())
128 .config(channel.config())
129 .handlers(new SnappyFrameDecoder())
130 .build();
131 }
132
133 if (Zstd.isAvailable() && ZSTD.contentEqualsIgnoreCase(contentEncoding)) {
134 return EmbeddedChannel.builder()
135 .channelId(channel.id())
136 .hasDisconnect(channel.metadata().hasDisconnect())
137 .config(channel.config())
138 .handlers(new ZstdDecoder())
139 .build();
140 }
141
142
143 return null;
144 }
145 }