1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.jboss.netty.handler.codec.http2;
17
18 import org.jboss.netty.buffer.ChannelBuffer;
19 import org.jboss.netty.buffer.ChannelBuffers;
20 import org.jboss.netty.channel.ChannelHandlerContext;
21 import org.jboss.netty.channel.Channels;
22 import org.jboss.netty.channel.MessageEvent;
23 import org.jboss.netty.channel.SimpleChannelUpstreamHandler;
24 import org.jboss.netty.handler.codec.embedder.DecoderEmbedder;
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49 public abstract class HttpContentDecoder extends SimpleChannelUpstreamHandler {
50
51 private DecoderEmbedder<ChannelBuffer> decoder;
52
53
54
55
56 protected HttpContentDecoder() {
57 super();
58 }
59
60 @Override
61 public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception {
62 Object msg = e.getMessage();
63 if (msg instanceof HttpResponse && ((HttpResponse) msg).getStatus().getCode() == 100) {
64
65 ctx.sendUpstream(e);
66 } else if (msg instanceof HttpMessage) {
67 HttpMessage m = (HttpMessage) msg;
68
69 decoder = null;
70
71
72 String contentEncoding = m.getHeader(HttpHeaders.Names.CONTENT_ENCODING);
73 if (contentEncoding != null) {
74 contentEncoding = contentEncoding.trim();
75 } else {
76 contentEncoding = HttpHeaders.Values.IDENTITY;
77 }
78
79 boolean hasContent = m.isChunked() || m.getContent().readable();
80 if (hasContent && (decoder = newContentDecoder(contentEncoding)) != null) {
81
82
83 m.setHeader(
84 HttpHeaders.Names.CONTENT_ENCODING,
85 getTargetContentEncoding(contentEncoding));
86
87 if (!m.isChunked()) {
88 ChannelBuffer content = m.getContent();
89
90 content = ChannelBuffers.wrappedBuffer(
91 decode(content), finishDecode());
92
93
94 m.setContent(content);
95 if (m.containsHeader(HttpHeaders.Names.CONTENT_LENGTH)) {
96 m.setHeader(
97 HttpHeaders.Names.CONTENT_LENGTH,
98 Integer.toString(content.readableBytes()));
99 }
100 }
101 }
102
103
104 ctx.sendUpstream(e);
105 } else if (msg instanceof HttpChunk) {
106 HttpChunk c = (HttpChunk) msg;
107 ChannelBuffer content = c.getContent();
108
109
110 if (decoder != null) {
111 if (!c.isLast()) {
112 content = decode(content);
113 if (content.readable()) {
114 c.setContent(content);
115 ctx.sendUpstream(e);
116 }
117 } else {
118 ChannelBuffer lastProduct = finishDecode();
119
120
121
122 if (lastProduct.readable()) {
123 Channels.fireMessageReceived(
124 ctx, new DefaultHttpChunk(lastProduct), e.getRemoteAddress());
125 }
126
127
128 ctx.sendUpstream(e);
129 }
130 } else {
131 ctx.sendUpstream(e);
132 }
133 } else {
134 ctx.sendUpstream(e);
135 }
136 }
137
138
139
140
141
142
143
144
145
146
147 protected abstract DecoderEmbedder<ChannelBuffer> newContentDecoder(String contentEncoding) throws Exception;
148
149
150
151
152
153
154
155
156
157 protected String getTargetContentEncoding(String contentEncoding) throws Exception {
158 return HttpHeaders.Values.IDENTITY;
159 }
160
161 private ChannelBuffer decode(ChannelBuffer buf) {
162 decoder.offer(buf);
163 return ChannelBuffers.wrappedBuffer(decoder.pollAll(new ChannelBuffer[decoder.size()]));
164 }
165
166 private ChannelBuffer finishDecode() {
167 ChannelBuffer result;
168 if (decoder.finish()) {
169 result = ChannelBuffers.wrappedBuffer(decoder.pollAll(new ChannelBuffer[decoder.size()]));
170 } else {
171 result = ChannelBuffers.EMPTY_BUFFER;
172 }
173 decoder = null;
174 return result;
175 }
176 }