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.buffer.ByteBuf;
19 import io.netty.channel.ChannelHandlerContext;
20 import io.netty.channel.CombinedChannelDuplexHandler;
21
22 import java.util.ArrayDeque;
23 import java.util.List;
24 import java.util.Queue;
25
26 import static io.netty.handler.codec.http.HttpObjectDecoder.DEFAULT_MAX_CHUNK_SIZE;
27 import static io.netty.handler.codec.http.HttpObjectDecoder.DEFAULT_MAX_HEADER_SIZE;
28 import static io.netty.handler.codec.http.HttpObjectDecoder.DEFAULT_MAX_INITIAL_LINE_LENGTH;
29 import static io.netty.handler.codec.http.HttpObjectDecoder.DEFAULT_VALIDATE_HEADERS;
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49 public final class HttpServerCodec extends CombinedChannelDuplexHandler<HttpRequestDecoder, HttpResponseEncoder>
50 implements HttpServerUpgradeHandler.SourceCodec {
51
52
53 private final Queue<HttpMethod> queue = new ArrayDeque<HttpMethod>();
54
55
56
57
58
59
60 public HttpServerCodec() {
61 this(DEFAULT_MAX_INITIAL_LINE_LENGTH, DEFAULT_MAX_HEADER_SIZE, DEFAULT_MAX_CHUNK_SIZE);
62 }
63
64
65
66
67 public HttpServerCodec(int maxInitialLineLength, int maxHeaderSize, int maxChunkSize) {
68 this(new HttpDecoderConfig()
69 .setMaxInitialLineLength(maxInitialLineLength)
70 .setMaxHeaderSize(maxHeaderSize)
71 .setMaxChunkSize(maxChunkSize));
72 }
73
74
75
76
77
78
79
80 @Deprecated
81 public HttpServerCodec(int maxInitialLineLength, int maxHeaderSize, int maxChunkSize, boolean validateHeaders) {
82 this(new HttpDecoderConfig()
83 .setMaxInitialLineLength(maxInitialLineLength)
84 .setMaxHeaderSize(maxHeaderSize)
85 .setMaxChunkSize(maxChunkSize)
86 .setValidateHeaders(validateHeaders));
87 }
88
89
90
91
92
93
94
95 @Deprecated
96 public HttpServerCodec(int maxInitialLineLength, int maxHeaderSize, int maxChunkSize, boolean validateHeaders,
97 int initialBufferSize) {
98 this(new HttpDecoderConfig()
99 .setMaxInitialLineLength(maxInitialLineLength)
100 .setMaxHeaderSize(maxHeaderSize)
101 .setMaxChunkSize(maxChunkSize)
102 .setValidateHeaders(validateHeaders)
103 .setInitialBufferSize(initialBufferSize));
104 }
105
106
107
108
109
110
111
112 @Deprecated
113 public HttpServerCodec(int maxInitialLineLength, int maxHeaderSize, int maxChunkSize, boolean validateHeaders,
114 int initialBufferSize, boolean allowDuplicateContentLengths) {
115 this(new HttpDecoderConfig()
116 .setMaxInitialLineLength(maxInitialLineLength)
117 .setMaxHeaderSize(maxHeaderSize)
118 .setMaxChunkSize(maxChunkSize)
119 .setValidateHeaders(validateHeaders)
120 .setInitialBufferSize(initialBufferSize)
121 .setAllowDuplicateContentLengths(allowDuplicateContentLengths));
122 }
123
124
125
126
127
128
129
130 @Deprecated
131 public HttpServerCodec(int maxInitialLineLength, int maxHeaderSize, int maxChunkSize, boolean validateHeaders,
132 int initialBufferSize, boolean allowDuplicateContentLengths, boolean allowPartialChunks) {
133 this(new HttpDecoderConfig()
134 .setMaxInitialLineLength(maxInitialLineLength)
135 .setMaxHeaderSize(maxHeaderSize)
136 .setMaxChunkSize(maxChunkSize)
137 .setValidateHeaders(validateHeaders)
138 .setInitialBufferSize(initialBufferSize)
139 .setAllowDuplicateContentLengths(allowDuplicateContentLengths)
140 .setAllowPartialChunks(allowPartialChunks));
141 }
142
143
144
145
146 public HttpServerCodec(HttpDecoderConfig config) {
147 init(new HttpServerRequestDecoder(config), new HttpServerResponseEncoder());
148 }
149
150
151
152
153
154 @Override
155 public void upgradeFrom(ChannelHandlerContext ctx) {
156 ctx.pipeline().remove(this);
157 }
158
159 private final class HttpServerRequestDecoder extends HttpRequestDecoder {
160 HttpServerRequestDecoder(HttpDecoderConfig config) {
161 super(config);
162 }
163
164 @Override
165 protected void decode(ChannelHandlerContext ctx, ByteBuf buffer, List<Object> out) throws Exception {
166 int oldSize = out.size();
167 super.decode(ctx, buffer, out);
168 int size = out.size();
169 for (int i = oldSize; i < size; i++) {
170 Object obj = out.get(i);
171 if (obj instanceof HttpRequest) {
172 queue.add(((HttpRequest) obj).method());
173 }
174 }
175 }
176 }
177
178 private final class HttpServerResponseEncoder extends HttpResponseEncoder {
179
180 private HttpMethod method;
181
182 @Override
183 protected void sanitizeHeadersBeforeEncode(HttpResponse msg, boolean isAlwaysEmpty) {
184 if (!isAlwaysEmpty && HttpMethod.CONNECT.equals(method)
185 && msg.status().codeClass() == HttpStatusClass.SUCCESS) {
186
187
188 msg.headers().remove(HttpHeaderNames.TRANSFER_ENCODING);
189 return;
190 }
191
192 super.sanitizeHeadersBeforeEncode(msg, isAlwaysEmpty);
193 }
194
195 @Override
196 protected boolean isContentAlwaysEmpty(@SuppressWarnings("unused") HttpResponse msg) {
197 method = queue.poll();
198 return HttpMethod.HEAD.equals(method) || super.isContentAlwaysEmpty(msg);
199 }
200 }
201 }