1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28 package org.apache.http.impl.nio.codecs;
29
30 import java.io.ByteArrayInputStream;
31 import java.io.IOException;
32 import java.nio.channels.Channels;
33 import java.nio.channels.ReadableByteChannel;
34 import java.nio.charset.Charset;
35
36 import org.apache.http.Consts;
37 import org.apache.http.HttpException;
38 import org.apache.http.HttpRequest;
39 import org.apache.http.HttpResponse;
40 import org.apache.http.HttpVersion;
41 import org.apache.http.config.MessageConstraints;
42 import org.apache.http.impl.nio.reactor.SessionInputBufferImpl;
43 import org.apache.http.nio.NHttpMessageParser;
44 import org.apache.http.nio.reactor.SessionInputBuffer;
45 import org.junit.Assert;
46 import org.junit.Test;
47
48
49
50
51 public class TestHttpMessageParser {
52
53 private static ReadableByteChannel newChannel(final String s, final Charset charset) {
54 return Channels.newChannel(new ByteArrayInputStream(s.getBytes(charset)));
55 }
56
57 private static ReadableByteChannel newChannel(final String s) {
58 return newChannel(s, Consts.ASCII);
59 }
60
61 @Test
62 public void testSimpleParsing() throws Exception {
63 final SessionInputBuffer inbuf = new SessionInputBufferImpl(1024, 128, Consts.ASCII);
64 final NHttpMessageParser<HttpRequest> requestParser = new DefaultHttpRequestParser(inbuf);
65 requestParser.fillBuffer(newChannel("GET /whatever HTTP/1.1\r\nSome header: stuff\r\n\r\n"));
66 final HttpRequest request = requestParser.parse();
67 Assert.assertNotNull(request);
68 Assert.assertEquals("/whatever", request.getRequestLine().getUri());
69 Assert.assertEquals(1, request.getAllHeaders().length);
70 }
71
72 @Test
73 public void testParsingChunkedMessages() throws Exception {
74 final SessionInputBuffer inbuf = new SessionInputBufferImpl(1024, 128, Consts.ASCII);
75 final NHttpMessageParser<HttpRequest> requestParser = new DefaultHttpRequestParser(inbuf);
76
77 requestParser.fillBuffer(newChannel("GET /whatev"));
78 HttpRequest request = requestParser.parse();
79 Assert.assertNull(request);
80 requestParser.fillBuffer(newChannel("er HTTP/1.1\r"));
81 request = requestParser.parse();
82 Assert.assertNull(request);
83 requestParser.fillBuffer(newChannel("\nSome header: stuff\r\n\r\n"));
84 request = requestParser.parse();
85
86 Assert.assertNotNull(request);
87 Assert.assertEquals("/whatever", request.getRequestLine().getUri());
88 Assert.assertEquals(1, request.getAllHeaders().length);
89
90 }
91
92 @Test
93 public void testParsingFoldedHeaders() throws Exception {
94 final SessionInputBuffer inbuf = new SessionInputBufferImpl(1024, 128, Consts.ASCII);
95 final NHttpMessageParser<HttpRequest> requestParser = new DefaultHttpRequestParser(inbuf);
96
97 requestParser.fillBuffer(newChannel("GET /whatev"));
98 HttpRequest request = requestParser.parse();
99 Assert.assertNull(request);
100 requestParser.fillBuffer(newChannel("er HTTP/1.1\r"));
101 request = requestParser.parse();
102 Assert.assertNull(request);
103 requestParser.fillBuffer(newChannel("\nSome header: stuff\r\n"));
104 request = requestParser.parse();
105 Assert.assertNull(request);
106 requestParser.fillBuffer(newChannel(" more\r\n"));
107 request = requestParser.parse();
108 Assert.assertNull(request);
109 requestParser.fillBuffer(newChannel("\tstuff\r\n"));
110 request = requestParser.parse();
111 Assert.assertNull(request);
112 requestParser.fillBuffer(newChannel("\r\n"));
113 request = requestParser.parse();
114
115 Assert.assertNotNull(request);
116 Assert.assertEquals("/whatever", request.getRequestLine().getUri());
117 Assert.assertEquals(1, request.getAllHeaders().length);
118 Assert.assertEquals("stuff more stuff", request.getFirstHeader("Some header").getValue());
119 }
120
121 @Test
122 public void testParsingBadlyFoldedFirstHeader() throws Exception {
123 final SessionInputBuffer inbuf = new SessionInputBufferImpl(1024, 128, Consts.ASCII);
124 final NHttpMessageParser<HttpRequest> requestParser = new DefaultHttpRequestParser(inbuf);
125
126 requestParser.fillBuffer(newChannel("GET /whatev"));
127 HttpRequest request = requestParser.parse();
128 Assert.assertNull(request);
129 requestParser.fillBuffer(newChannel("er HTTP/1.1\r"));
130 request = requestParser.parse();
131 Assert.assertNull(request);
132 requestParser.fillBuffer(newChannel("\n Some header: stuff\r\n"));
133 request = requestParser.parse();
134 Assert.assertNull(request);
135 requestParser.fillBuffer(newChannel(" more stuff\r\n"));
136 request = requestParser.parse();
137 Assert.assertNull(request);
138 requestParser.fillBuffer(newChannel("\r\n"));
139 request = requestParser.parse();
140
141 Assert.assertNotNull(request);
142 Assert.assertEquals("/whatever", request.getRequestLine().getUri());
143 Assert.assertEquals(1, request.getAllHeaders().length);
144 Assert.assertEquals("stuff more stuff", request.getFirstHeader("Some header").getValue());
145 }
146
147 @Test
148 public void testParsingEmptyFoldedHeader() throws Exception {
149 final SessionInputBuffer inbuf = new SessionInputBufferImpl(1024, 128, Consts.ASCII);
150 final NHttpMessageParser<HttpRequest> requestParser = new DefaultHttpRequestParser(inbuf);
151
152 requestParser.fillBuffer(newChannel("GET /whatev"));
153 HttpRequest request = requestParser.parse();
154 Assert.assertNull(request);
155 requestParser.fillBuffer(newChannel("er HTTP/1.1\r"));
156 request = requestParser.parse();
157 Assert.assertNull(request);
158 requestParser.fillBuffer(newChannel("\n Some header: stuff\r\n"));
159 request = requestParser.parse();
160 Assert.assertNull(request);
161 requestParser.fillBuffer(newChannel(" \r\n"));
162 request = requestParser.parse();
163 Assert.assertNull(request);
164 requestParser.fillBuffer(newChannel(" more stuff\r\n"));
165 request = requestParser.parse();
166 Assert.assertNull(request);
167 requestParser.fillBuffer(newChannel("\r\n"));
168 request = requestParser.parse();
169
170 Assert.assertNotNull(request);
171 Assert.assertEquals("/whatever", request.getRequestLine().getUri());
172 Assert.assertEquals(1, request.getAllHeaders().length);
173 Assert.assertEquals("stuff more stuff", request.getFirstHeader("Some header").getValue());
174 }
175
176 @Test
177 public void testParsingIncompleteRequestLine() throws Exception {
178 final SessionInputBuffer inbuf = new SessionInputBufferImpl(1024, 128, Consts.ASCII);
179 final NHttpMessageParser<HttpRequest> requestParser = new DefaultHttpRequestParser(inbuf);
180
181 final ReadableByteChannel channel = newChannel("GET /whatever HTTP/1.0");
182 requestParser.fillBuffer(channel);
183 requestParser.fillBuffer(channel);
184 final HttpRequest request = requestParser.parse();
185 Assert.assertNotNull(request);
186 Assert.assertEquals(HttpVersion.HTTP_1_0, request.getRequestLine().getProtocolVersion());
187 }
188
189 @Test
190 public void testParsingIncompleteHeader() throws Exception {
191 final SessionInputBuffer inbuf = new SessionInputBufferImpl(1024, 128, Consts.ASCII);
192 final NHttpMessageParser<HttpRequest> requestParser = new DefaultHttpRequestParser(inbuf);
193
194 final ReadableByteChannel channel = newChannel("GET /whatever HTTP/1.0\r\nHeader: whatever");
195 requestParser.fillBuffer(channel);
196 requestParser.fillBuffer(channel);
197 final HttpRequest request = requestParser.parse();
198 Assert.assertNotNull(request);
199 Assert.assertEquals(1, request.getAllHeaders().length);
200 Assert.assertEquals("whatever", request.getFirstHeader("Header").getValue());
201 }
202
203 @Test
204 public void testParsingInvalidRequestLine() throws Exception {
205 final SessionInputBuffer inbuf = new SessionInputBufferImpl(1024, 128, Consts.ASCII);
206 final NHttpMessageParser<HttpRequest> requestParser = new DefaultHttpRequestParser(inbuf);
207
208 final ReadableByteChannel channel = newChannel("GET garbage\r\n");
209 requestParser.fillBuffer(channel);
210 try {
211 requestParser.parse();
212 Assert.fail("HttpException should have been thrown");
213 } catch (final HttpException ex) {
214
215 }
216 }
217
218 @Test
219 public void testParsingInvalidStatusLine() throws Exception {
220 final SessionInputBuffer inbuf = new SessionInputBufferImpl(1024, 128, Consts.ASCII);
221 final NHttpMessageParser<HttpResponse> responseParser = new DefaultHttpResponseParser(inbuf);
222
223 final ReadableByteChannel channel = newChannel("HTTP 200 OK\r\n");
224 responseParser.fillBuffer(channel);
225 try {
226 responseParser.parse();
227 Assert.fail("HttpException should have been thrown");
228 } catch (final HttpException ex) {
229
230 }
231 }
232
233 @Test
234 public void testParsingInvalidHeader() throws Exception {
235 final SessionInputBuffer inbuf = new SessionInputBufferImpl(1024, 128, Consts.ASCII);
236 final NHttpMessageParser<HttpResponse> responseParser = new DefaultHttpResponseParser(inbuf);
237
238 final ReadableByteChannel channel = newChannel("HTTP/1.0 200 OK\r\nstuff\r\n\r\n");
239 responseParser.fillBuffer(channel);
240 try {
241 responseParser.parse();
242 Assert.fail("HttpException should have been thrown");
243 } catch (final HttpException ex) {
244
245 }
246 }
247
248 @Test
249 public void testResetParser() throws Exception {
250 final SessionInputBuffer inbuf = new SessionInputBufferImpl(1024, 128, Consts.ASCII);
251 final NHttpMessageParser<HttpRequest> requestParser = new DefaultHttpRequestParser(inbuf);
252
253 ReadableByteChannel channel = newChannel("GET /whatever HTTP/1.0\r\nHeader: one\r\n\r\n");
254 requestParser.fillBuffer(channel);
255 HttpRequest request = requestParser.parse();
256 Assert.assertNotNull(request);
257 Assert.assertEquals(1, request.getAllHeaders().length);
258 Assert.assertEquals("one", request.getFirstHeader("Header").getValue());
259
260 requestParser.reset();
261
262 channel = newChannel("GET /whatever HTTP/1.0\r\nHeader: two\r\n\r\n");
263 requestParser.fillBuffer(channel);
264 request = requestParser.parse();
265 Assert.assertNotNull(request);
266 Assert.assertEquals(1, request.getAllHeaders().length);
267 Assert.assertEquals("two", request.getFirstHeader("Header").getValue());
268 }
269
270 @Test
271 public void testInvalidConstructor() {
272 try {
273 new DefaultHttpRequestParser(null);
274 Assert.fail("IllegalArgumentException should have been thrown");
275 } catch (final IllegalArgumentException ex) {
276
277 }
278 }
279
280 @Test
281 public void testLineLimitForStatus() throws Exception {
282 final SessionInputBuffer inbuf = new SessionInputBufferImpl(1024, 128, Consts.ASCII);
283 NHttpMessageParser<HttpRequest> requestParser = new DefaultHttpRequestParser(inbuf,
284 MessageConstraints.lineLen(0));
285 requestParser.fillBuffer(newChannel("GET /whatever HTTP/1.0\r\nHeader: one\r\n\r\n"));
286 requestParser.parse();
287 requestParser.reset();
288
289 requestParser = new DefaultHttpRequestParser(inbuf, MessageConstraints.lineLen(15));
290 try {
291 requestParser.fillBuffer(newChannel("GET /loooooooooooooooong HTTP/1.0\r\nHeader: one\r\n\r\n"));
292 requestParser.parse();
293 Assert.fail("IOException should have been thrown");
294 } catch (final IOException expected) {
295 }
296 }
297
298 @Test
299 public void testLineLimitForHeader() throws Exception {
300 final SessionInputBuffer inbuf = new SessionInputBufferImpl(1024, 128, Consts.ASCII);
301
302 NHttpMessageParser<HttpRequest> requestParser = new DefaultHttpRequestParser(inbuf,
303 MessageConstraints.lineLen(0));
304 requestParser.fillBuffer(newChannel("GET /whatever HTTP/1.0\r\nHeader: one\r\n\r\n"));
305 requestParser.parse();
306 requestParser.reset();
307
308 requestParser = new DefaultHttpRequestParser(inbuf, MessageConstraints.lineLen(15));
309 requestParser.fillBuffer(newChannel("GET / HTTP/1.0\r\nHeader: 9012345\r\n\r\n"));
310 requestParser.parse();
311 requestParser.reset();
312 try {
313 requestParser.fillBuffer(newChannel("GET / HTTP/1.0\r\nHeader: 90123456\r\n\r\n"));
314 requestParser.parse();
315 Assert.fail("IOException should have been thrown");
316 } catch (final IOException expected) {
317 }
318 }
319
320 @Test
321 public void testLineLimitForFoldedHeader() throws Exception {
322 final SessionInputBuffer inbuf = new SessionInputBufferImpl(1024, 128, Consts.ASCII);
323
324 final MessageConstraints constraints = MessageConstraints.custom()
325 .setMaxHeaderCount(2).setMaxLineLength(15).build();
326 final NHttpMessageParser<HttpRequest> requestParser = new DefaultHttpRequestParser(inbuf, constraints);
327 try {
328 requestParser.fillBuffer(newChannel("GET / HTTP/1.0\r\nHeader: 9012345\r\n" +
329 " 23456789012345\r\n 23456789012345\r\n 23456789012345\r\n\r\n"));
330 requestParser.parse();
331 Assert.fail("IOException should have been thrown");
332 } catch (final IOException expected) {
333 }
334 }
335
336 @Test
337 public void testMaxHeaderCount() throws Exception {
338 final SessionInputBuffer inbuf = new SessionInputBufferImpl(1024, 128, Consts.ASCII);
339
340 final MessageConstraints constraints = MessageConstraints.custom()
341 .setMaxHeaderCount(2).setMaxLineLength(-1).build();
342 final NHttpMessageParser<HttpRequest> requestParser = new DefaultHttpRequestParser(inbuf, constraints);
343 requestParser.fillBuffer(newChannel("GET /whatever HTTP/1.0\r\nHeader: one\r\nHeader: two\r\n\r\n"));
344 requestParser.parse();
345 requestParser.reset();
346
347 try {
348 requestParser.fillBuffer(newChannel("GET /whatever HTTP/1.0\r\nHeader: one\r\n" +
349 "Header: two\r\nHeader: three\r\n\r\n"));
350 requestParser.parse();
351 Assert.fail("IOException should have been thrown");
352 } catch (final IOException expected) {
353 }
354 }
355
356 @Test
357 public void testDetectLineLimitEarly() throws Exception {
358 final SessionInputBuffer inbuf = new SessionInputBufferImpl(2, 128, Consts.ASCII);
359
360 final NHttpMessageParser<HttpRequest> requestParser = new DefaultHttpRequestParser(inbuf,
361 MessageConstraints.lineLen(2));
362 final ReadableByteChannel channel = newChannel("GET / HTTP/1.0\r\nHeader: one\r\n\r\n");
363 Assert.assertEquals(2, requestParser.fillBuffer(channel));
364 Assert.assertNull(requestParser.parse());
365 Assert.assertEquals(4, requestParser.fillBuffer(channel));
366 try {
367 requestParser.parse();
368 Assert.fail("IOException should have been thrown");
369 } catch (final IOException expected) {
370 }
371 }
372
373 }