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
27
28
29
30
31
32 public final class HttpServerCodec
33 extends CombinedChannelDuplexHandler<HttpRequestDecoder, HttpResponseEncoder> {
34
35
36 private final Queue<HttpMethod> queue = new ArrayDeque<HttpMethod>();
37
38
39
40
41
42
43 public HttpServerCodec() {
44 this(4096, 8192, 8192);
45 }
46
47
48
49
50 public HttpServerCodec(int maxInitialLineLength, int maxHeaderSize, int maxChunkSize) {
51 init(new HttpServerRequestDecoder(maxInitialLineLength, maxHeaderSize, maxChunkSize),
52 new HttpServerResponseEncoder());
53 }
54
55
56
57
58 public HttpServerCodec(int maxInitialLineLength, int maxHeaderSize, int maxChunkSize, boolean validateHeaders) {
59 init(new HttpServerRequestDecoder(maxInitialLineLength, maxHeaderSize, maxChunkSize, validateHeaders),
60 new HttpServerResponseEncoder());
61 }
62
63
64
65
66 public HttpServerCodec(int maxInitialLineLength, int maxHeaderSize, int maxChunkSize, boolean validateHeaders,
67 int initialBufferSize) {
68 init(
69 new HttpServerRequestDecoder(maxInitialLineLength, maxHeaderSize, maxChunkSize,
70 validateHeaders, initialBufferSize),
71 new HttpServerResponseEncoder());
72 }
73
74 private final class HttpServerRequestDecoder extends HttpRequestDecoder {
75 HttpServerRequestDecoder(int maxInitialLineLength, int maxHeaderSize, int maxChunkSize) {
76 super(maxInitialLineLength, maxHeaderSize, maxChunkSize);
77 }
78
79 HttpServerRequestDecoder(int maxInitialLineLength, int maxHeaderSize, int maxChunkSize,
80 boolean validateHeaders) {
81 super(maxInitialLineLength, maxHeaderSize, maxChunkSize, validateHeaders);
82 }
83
84 HttpServerRequestDecoder(int maxInitialLineLength, int maxHeaderSize, int maxChunkSize,
85 boolean validateHeaders, int initialBufferSize) {
86 super(maxInitialLineLength, maxHeaderSize, maxChunkSize, validateHeaders, initialBufferSize);
87 }
88
89 @Override
90 protected void decode(ChannelHandlerContext ctx, ByteBuf buffer, List<Object> out) throws Exception {
91 int oldSize = out.size();
92 super.decode(ctx, buffer, out);
93 int size = out.size();
94 for (int i = oldSize; i < size; i++) {
95 Object obj = out.get(i);
96 if (obj instanceof HttpRequest) {
97 queue.add(((HttpRequest) obj).getMethod());
98 }
99 }
100 }
101 }
102
103 private final class HttpServerResponseEncoder extends HttpResponseEncoder {
104
105 private HttpMethod method;
106
107 @Override
108 protected void sanitizeHeadersBeforeEncode(HttpResponse msg, boolean isAlwaysEmpty) {
109 int code = msg.getStatus().code();
110 if (!isAlwaysEmpty && method == HttpMethod.CONNECT && code >= 200 && code <= 299) {
111
112
113 msg.headers().remove(HttpHeaders.Names.TRANSFER_ENCODING);
114 return;
115 }
116
117 super.sanitizeHeadersBeforeEncode(msg, isAlwaysEmpty);
118 }
119
120 @Override
121 protected boolean isContentAlwaysEmpty(@SuppressWarnings("unused") HttpResponse msg) {
122 method = queue.poll();
123 return HttpMethod.HEAD.equals(method) || super.isContentAlwaysEmpty(msg);
124 }
125 }
126 }