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