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.buffer.Unpooled;
20  import io.netty.channel.ChannelPipeline;
21  import io.netty.util.AsciiString;
22  
23  
24  
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  
50  
51  
52  
53  
54  
55  
56  
57  
58  
59  
60  
61  
62  
63  
64  
65  
66  
67  
68  
69  
70  
71  
72  
73  
74  
75  
76  
77  
78  
79  
80  
81  
82  
83  
84  
85  
86  
87  
88  
89  
90  
91  public class HttpRequestDecoder extends HttpObjectDecoder {
92  
93      private static final AsciiString Accept = AsciiString.cached("Accept");
94      private static final AsciiString Host = AsciiString.cached("Host");
95      private static final AsciiString Connection = AsciiString.cached("Connection");
96      private static final AsciiString ContentType = AsciiString.cached("Content-Type");
97      private static final AsciiString ContentLength = AsciiString.cached("Content-Length");
98  
99      private static final int GET_AS_INT = 'G' | 'E' << 8 | 'T' << 16;
100     private static final int POST_AS_INT = 'P' | 'O' << 8 | 'S' << 16 | 'T' << 24;
101     private static final long HTTP_1_1_AS_LONG = 'H' | 'T' << 8 | 'T' << 16 | 'P' << 24 | (long) '/' << 32 |
102             (long) '1' << 40 | (long) '.' << 48 | (long) '1' << 56;
103 
104     private static final long HTTP_1_0_AS_LONG = 'H' | 'T' << 8 | 'T' << 16 | 'P' << 24 | (long) '/' << 32 |
105             (long) '1' << 40 | (long) '.' << 48 | (long) '0' << 56;
106 
107     private static final int HOST_AS_INT = 'H' | 'o' << 8 | 's' << 16 | 't' << 24;
108 
109     private static final long CONNECTION_AS_LONG_0 = 'C' | 'o' << 8 | 'n' << 16 | 'n' << 24 |
110             (long) 'e' << 32 | (long) 'c' << 40 | (long) 't' << 48 | (long) 'i' << 56;
111 
112     private static final short CONNECTION_AS_SHORT_1 = 'o' | 'n' << 8;
113 
114     private static final long CONTENT_AS_LONG = 'C' | 'o' << 8 | 'n' << 16 | 't' << 24 |
115             (long) 'e' << 32 | (long) 'n' << 40 | (long) 't' << 48 | (long) '-' << 56;
116 
117     private static final int TYPE_AS_INT = 'T' | 'y' << 8 | 'p' << 16 | 'e' << 24;
118 
119     private static final long LENGTH_AS_LONG = 'L' | 'e' << 8 | 'n' << 16 | 'g' << 24 |
120             (long) 't' << 32 | (long) 'h' << 40;
121 
122     private static final long ACCEPT_AS_LONG = 'A' | 'c' << 8 | 'c' << 16 | 'e' << 24 |
123             (long) 'p' << 32 | (long) 't' << 40;
124 
125     
126 
127 
128 
129 
130 
131 
132     public HttpRequestDecoder() {
133     }
134 
135     
136 
137 
138 
139 
140 
141 
142 
143 
144 
145 
146     public HttpRequestDecoder(
147             int maxInitialLineLength, int maxHeaderSize, int maxChunkSize) {
148         this(new HttpDecoderConfig()
149                 .setMaxInitialLineLength(maxInitialLineLength)
150                 .setMaxHeaderSize(maxHeaderSize)
151                 .setMaxChunkSize(maxChunkSize));
152     }
153 
154     
155 
156 
157 
158 
159 
160     @Deprecated
161     public HttpRequestDecoder(
162             int maxInitialLineLength, int maxHeaderSize, int maxChunkSize, boolean validateHeaders) {
163         super(maxInitialLineLength, maxHeaderSize, maxChunkSize, DEFAULT_CHUNKED_SUPPORTED, validateHeaders);
164     }
165 
166     
167 
168 
169 
170 
171 
172     @Deprecated
173     public HttpRequestDecoder(
174             int maxInitialLineLength, int maxHeaderSize, int maxChunkSize, boolean validateHeaders,
175             int initialBufferSize) {
176         super(maxInitialLineLength, maxHeaderSize, maxChunkSize, DEFAULT_CHUNKED_SUPPORTED, validateHeaders,
177               initialBufferSize);
178     }
179 
180     
181 
182 
183 
184 
185 
186     @Deprecated
187     public HttpRequestDecoder(
188             int maxInitialLineLength, int maxHeaderSize, int maxChunkSize, boolean validateHeaders,
189             int initialBufferSize, boolean allowDuplicateContentLengths) {
190         super(maxInitialLineLength, maxHeaderSize, maxChunkSize, DEFAULT_CHUNKED_SUPPORTED, validateHeaders,
191               initialBufferSize, allowDuplicateContentLengths);
192     }
193 
194     
195 
196 
197 
198 
199 
200     @Deprecated
201     public HttpRequestDecoder(
202             int maxInitialLineLength, int maxHeaderSize, int maxChunkSize, boolean validateHeaders,
203             int initialBufferSize, boolean allowDuplicateContentLengths, boolean allowPartialChunks) {
204         super(maxInitialLineLength, maxHeaderSize, maxChunkSize, DEFAULT_CHUNKED_SUPPORTED, validateHeaders,
205               initialBufferSize, allowDuplicateContentLengths, allowPartialChunks);
206     }
207 
208     
209 
210 
211 
212 
213     public HttpRequestDecoder(HttpDecoderConfig config) {
214         super(config);
215     }
216 
217     @Override
218     protected HttpMessage createMessage(String[] initialLine) throws Exception {
219         return new DefaultHttpRequest(
220                 
221                 HttpVersion.valueOf(initialLine[2], true),
222                 HttpMethod.valueOf(initialLine[0]), initialLine[1], headersFactory);
223     }
224 
225     @Override
226     protected AsciiString splitHeaderName(final byte[] sb, final int start, final int length) {
227         final byte firstChar = sb[start];
228         if (firstChar == 'H') {
229             if (length == 4 && isHost(sb, start)) {
230                 return Host;
231             }
232         } else if (firstChar == 'A') {
233             if (length == 6 && isAccept(sb, start)) {
234                 return Accept;
235             }
236         } else if (firstChar == 'C') {
237             if (length == 10) {
238                 if (isConnection(sb, start)) {
239                     return Connection;
240                 }
241             } else if (length == 12) {
242                 if (isContentType(sb, start)) {
243                     return ContentType;
244                 }
245             } else if (length == 14) {
246                 if (isContentLength(sb, start)) {
247                     return ContentLength;
248                 }
249             }
250         }
251         return super.splitHeaderName(sb, start, length);
252     }
253 
254     private static boolean isAccept(byte[] sb, int start) {
255         final long maybeAccept = sb[start] |
256                 sb[start + 1] << 8 |
257                 sb[start + 2] << 16 |
258                 sb[start + 3] << 24 |
259                 (long) sb[start + 4] << 32 |
260                 (long) sb[start + 5] << 40;
261         return maybeAccept == ACCEPT_AS_LONG;
262     }
263 
264     private static boolean isHost(byte[] sb, int start) {
265         final int maybeHost = sb[start] |
266                 sb[start + 1] << 8 |
267                 sb[start + 2] << 16 |
268                 sb[start + 3] << 24;
269         return maybeHost == HOST_AS_INT;
270     }
271 
272     private static boolean isConnection(byte[] sb, int start) {
273         final long maybeConnecti = sb[start] |
274                 sb[start + 1] << 8 |
275                 sb[start + 2] << 16 |
276                 sb[start + 3] << 24 |
277                 (long) sb[start + 4] << 32 |
278                 (long) sb[start + 5] << 40 |
279                 (long) sb[start + 6] << 48 |
280                 (long) sb[start + 7] << 56;
281         if (maybeConnecti != CONNECTION_AS_LONG_0) {
282             return false;
283         }
284         final short maybeOn = (short) (sb[start + 8] | sb[start + 9] << 8);
285         return maybeOn == CONNECTION_AS_SHORT_1;
286     }
287 
288     private static boolean isContentType(byte[] sb, int start) {
289         final long maybeContent = sb[start] |
290                 sb[start + 1] << 8 |
291                 sb[start + 2] << 16 |
292                 sb[start + 3] << 24 |
293                 (long) sb[start + 4] << 32 |
294                 (long) sb[start + 5] << 40 |
295                 (long) sb[start + 6] << 48 |
296                 (long) sb[start + 7] << 56;
297         if (maybeContent != CONTENT_AS_LONG) {
298             return false;
299         }
300         final int maybeType = sb[start + 8] |
301                 sb[start + 9] << 8 |
302                 sb[start + 10] << 16 |
303                 sb[start + 11] << 24;
304         return maybeType == TYPE_AS_INT;
305     }
306 
307     private static boolean isContentLength(byte[] sb, int start) {
308         final long maybeContent = sb[start] |
309                 sb[start + 1] << 8 |
310                 sb[start + 2] << 16 |
311                 sb[start + 3] << 24 |
312                 (long) sb[start + 4] << 32 |
313                 (long) sb[start + 5] << 40 |
314                 (long) sb[start + 6] << 48 |
315                 (long) sb[start + 7] << 56;
316         if (maybeContent != CONTENT_AS_LONG) {
317             return false;
318         }
319         final long maybeLength = sb[start + 8] |
320                 sb[start + 9] << 8 |
321                 sb[start + 10] << 16 |
322                 sb[start + 11] << 24 |
323                 (long) sb[start + 12] << 32 |
324                 (long) sb[start + 13] << 40;
325         return maybeLength == LENGTH_AS_LONG;
326     }
327 
328     private static boolean isGetMethod(final byte[] sb, int start) {
329         final int maybeGet = sb[start] |
330                 sb[start + 1] << 8 |
331                 sb[start + 2] << 16;
332         return maybeGet == GET_AS_INT;
333     }
334 
335     private static boolean isPostMethod(final byte[] sb, int start) {
336         final int maybePost = sb[start] |
337                 sb[start + 1] << 8 |
338                 sb[start + 2] << 16 |
339                 sb[start + 3] << 24;
340         return maybePost == POST_AS_INT;
341     }
342 
343     @Override
344     protected String splitFirstWordInitialLine(final byte[] sb, final int start, final int length) {
345         if (length == 3) {
346             if (isGetMethod(sb, start)) {
347                 return HttpMethod.GET.name();
348             }
349         } else if (length == 4) {
350             if (isPostMethod(sb, start)) {
351                 return HttpMethod.POST.name();
352             }
353         }
354         return super.splitFirstWordInitialLine(sb, start, length);
355     }
356 
357     @Override
358     protected String splitThirdWordInitialLine(final byte[] sb, final int start, final int length) {
359         if (length == 8) {
360             final long maybeHttp1_x = sb[start] |
361                     sb[start + 1] << 8 |
362                     sb[start + 2] << 16 |
363                     sb[start + 3] << 24 |
364                     (long) sb[start + 4] << 32 |
365                     (long) sb[start + 5] << 40 |
366                     (long) sb[start + 6] << 48 |
367                     (long) sb[start + 7] << 56;
368             if (maybeHttp1_x == HTTP_1_1_AS_LONG) {
369                 return HttpVersion.HTTP_1_1_STRING;
370             } else if (maybeHttp1_x == HTTP_1_0_AS_LONG) {
371                 return HttpVersion.HTTP_1_0_STRING;
372             }
373         }
374         return super.splitThirdWordInitialLine(sb, start, length);
375     }
376 
377     @Override
378     protected HttpMessage createInvalidMessage() {
379         return new DefaultFullHttpRequest(HttpVersion.HTTP_1_0, HttpMethod.GET, "/bad-request",
380                 Unpooled.buffer(0), headersFactory, trailersFactory);
381     }
382 
383     @Override
384     protected boolean isDecodingRequest() {
385         return true;
386     }
387 
388     @Override
389     protected boolean isContentAlwaysEmpty(final HttpMessage msg) {
390         
391         
392         
393         if (msg.getClass() == DefaultHttpRequest.class) {
394             return false;
395         }
396         return super.isContentAlwaysEmpty(msg);
397     }
398 }