View Javadoc
1   /*
2    * ====================================================================
3    * Licensed to the Apache Software Foundation (ASF) under one
4    * or more contributor license agreements.  See the NOTICE file
5    * distributed with this work for additional information
6    * regarding copyright ownership.  The ASF licenses this file
7    * to you under the Apache License, Version 2.0 (the
8    * "License"); you may not use this file except in compliance
9    * with the License.  You may obtain a copy of the License at
10   *
11   *   http://www.apache.org/licenses/LICENSE-2.0
12   *
13   * Unless required by applicable law or agreed to in writing,
14   * software distributed under the License is distributed on an
15   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16   * KIND, either express or implied.  See the License for the
17   * specific language governing permissions and limitations
18   * under the License.
19   * ====================================================================
20   *
21   * This software consists of voluntary contributions made by many
22   * individuals on behalf of the Apache Software Foundation.  For more
23   * information on the Apache Software Foundation, please see
24   * <http://www.apache.org/>.
25   *
26   */
27  
28  package org.apache.hc.core5.http.message;
29  
30  import org.apache.hc.core5.http.Header;
31  import org.apache.hc.core5.http.HttpVersion;
32  import org.apache.hc.core5.http.ParseException;
33  import org.apache.hc.core5.util.CharArrayBuffer;
34  import org.junit.Assert;
35  import org.junit.Before;
36  import org.junit.Test;
37  
38  /**
39   * Tests for {@link BasicLineParser}.
40   *
41   */
42  public class TestBasicLineParser {
43  
44      private BasicLineParser parser;
45  
46      @Before
47      public void setup() {
48          this.parser = BasicLineParser.INSTANCE;
49      }
50  
51      @Test
52      public void testRLParse() throws Exception {
53          final CharArrayBuffer buf = new CharArrayBuffer(64);
54          //typical request line
55          buf.clear();
56          buf.append("GET /stuff HTTP/1.1");
57          RequestLine requestline = this.parser.parseRequestLine(buf);
58          Assert.assertEquals("GET /stuff HTTP/1.1", requestline.toString());
59          Assert.assertEquals("GET", requestline.getMethod());
60          Assert.assertEquals("/stuff", requestline.getUri());
61          Assert.assertEquals(HttpVersion.HTTP_1_1, requestline.getProtocolVersion());
62  
63          //Lots of blanks
64          buf.clear();
65          buf.append("  GET    /stuff   HTTP/1.1   ");
66          requestline = this.parser.parseRequestLine(buf);
67          Assert.assertEquals("GET /stuff HTTP/1.1", requestline.toString());
68          Assert.assertEquals("GET", requestline.getMethod());
69          Assert.assertEquals("/stuff", requestline.getUri());
70          Assert.assertEquals(HttpVersion.HTTP_1_1, requestline.getProtocolVersion());
71  
72          //this is not strictly valid, but is lenient
73          buf.clear();
74          buf.append("\rGET /stuff HTTP/1.1");
75          requestline = this.parser.parseRequestLine(buf);
76          Assert.assertEquals("GET", requestline.getMethod());
77          Assert.assertEquals("/stuff", requestline.getUri());
78          Assert.assertEquals(HttpVersion.HTTP_1_1, requestline.getProtocolVersion());
79      }
80  
81      @Test
82      public void testRLParseFailure() throws Exception {
83          final CharArrayBuffer buf = new CharArrayBuffer(64);
84          buf.clear();
85          buf.append("    ");
86          try {
87              this.parser.parseRequestLine(buf);
88              Assert.fail();
89          } catch (final ParseException e) {
90              // expected
91          }
92          buf.clear();
93          buf.append("  GET");
94          try {
95              this.parser.parseRequestLine(buf);
96              Assert.fail();
97          } catch (final ParseException e) {
98              // expected
99          }
100         buf.clear();
101         buf.append("GET /stuff");
102         try {
103             this.parser.parseRequestLine(buf);
104             Assert.fail();
105         } catch (final ParseException e) {
106             // expected
107         }
108         buf.clear();
109         buf.append("GET/stuff HTTP/1.1");
110         try {
111             this.parser.parseRequestLine(buf);
112             Assert.fail();
113         } catch (final ParseException e) {
114             // expected
115         }
116         buf.clear();
117         buf.append("GET /stuff HTTP/1.1 Oooooooooooppsie");
118         try {
119             this.parser.parseRequestLine(buf);
120             Assert.fail();
121         } catch (final ParseException e) {
122             // expected
123         }
124     }
125 
126     @Test
127     public void testSLParse() throws Exception {
128         final CharArrayBuffer buf = new CharArrayBuffer(64);
129         //typical status line
130         buf.clear();
131         buf.append("HTTP/1.1 200 OK");
132         StatusLine statusLine = this.parser.parseStatusLine(buf);
133         Assert.assertEquals("HTTP/1.1 200 OK", statusLine.toString());
134         Assert.assertEquals(HttpVersion.HTTP_1_1, statusLine.getProtocolVersion());
135         Assert.assertEquals(200, statusLine.getStatusCode());
136         Assert.assertEquals("OK", statusLine.getReasonPhrase());
137 
138         //status line with multi word reason phrase
139         buf.clear();
140         buf.append("HTTP/1.1 404 Not Found");
141         statusLine = this.parser.parseStatusLine(buf);
142         Assert.assertEquals(404, statusLine.getStatusCode());
143         Assert.assertEquals("Not Found", statusLine.getReasonPhrase());
144 
145         //reason phrase can be anyting
146         buf.clear();
147         buf.append("HTTP/1.1 404 Non Trouve");
148         statusLine = this.parser.parseStatusLine(buf);
149         Assert.assertEquals("Non Trouve", statusLine.getReasonPhrase());
150 
151         //its ok to end with a \n\r
152         buf.clear();
153         buf.append("HTTP/1.1 404 Not Found\r\n");
154         statusLine = this.parser.parseStatusLine(buf);
155         Assert.assertEquals("Not Found", statusLine.getReasonPhrase());
156 
157         //this is valid according to the Status-Line BNF
158         buf.clear();
159         buf.append("HTTP/1.1 200 ");
160         statusLine = this.parser.parseStatusLine(buf);
161         Assert.assertEquals(200, statusLine.getStatusCode());
162         Assert.assertEquals("", statusLine.getReasonPhrase());
163 
164         //this is not strictly valid, but is lenient
165         buf.clear();
166         buf.append("HTTP/1.1 200");
167         statusLine = this.parser.parseStatusLine(buf);
168         Assert.assertEquals(200, statusLine.getStatusCode());
169         Assert.assertEquals("", statusLine.getReasonPhrase());
170 
171         //this is not strictly valid, but is lenient
172         buf.clear();
173         buf.append("HTTP/1.1     200 OK");
174         statusLine = this.parser.parseStatusLine(buf);
175         Assert.assertEquals(200, statusLine.getStatusCode());
176         Assert.assertEquals("OK", statusLine.getReasonPhrase());
177 
178         //this is not strictly valid, but is lenient
179         buf.clear();
180         buf.append("\nHTTP/1.1 200 OK");
181         statusLine = this.parser.parseStatusLine(buf);
182         Assert.assertEquals(200, statusLine.getStatusCode());
183         Assert.assertEquals("OK", statusLine.getReasonPhrase());
184         Assert.assertEquals(HttpVersion.HTTP_1_1, statusLine.getProtocolVersion());
185 
186         //this is not strictly valid, but is lenient
187         buf.clear();
188         buf.append("  HTTP/1.1 200 OK");
189         statusLine = this.parser.parseStatusLine(buf);
190         Assert.assertEquals(200, statusLine.getStatusCode());
191         Assert.assertEquals("OK", statusLine.getReasonPhrase());
192         Assert.assertEquals(HttpVersion.HTTP_1_1, statusLine.getProtocolVersion());
193     }
194 
195     @Test
196     public void testSLParseFailure() throws Exception {
197         final CharArrayBuffer buf = new CharArrayBuffer(64);
198         buf.clear();
199         buf.append("xxx 200 OK");
200         try {
201             this.parser.parseStatusLine(buf);
202             Assert.fail();
203         } catch (final ParseException e) {
204             // expected
205         }
206         buf.clear();
207         buf.append("HTTP/1.1 xxx OK");
208         try {
209             this.parser.parseStatusLine(buf);
210             Assert.fail();
211         } catch (final ParseException e) {
212             // expected
213         }
214         buf.clear();
215         buf.append("HTTP/1.1    ");
216         try {
217             this.parser.parseStatusLine(buf);
218             Assert.fail();
219         } catch (final ParseException e) {
220             // expected
221         }
222         buf.clear();
223         buf.append("HTTP/1.1");
224         try {
225             this.parser.parseStatusLine(buf);
226             Assert.fail();
227         } catch (final ParseException e) {
228             // expected
229         }
230         buf.clear();
231         buf.append("HTTP/1.1 -200 OK");
232         try {
233             this.parser.parseStatusLine(buf);
234             Assert.fail();
235         } catch (final ParseException e) {
236             // expected
237         }
238     }
239 
240     @Test
241     public void testHttpVersionParsing() throws Exception {
242         final CharArrayBuffer buffer = new CharArrayBuffer(16);
243         buffer.append("HTTP/1.1");
244         ParserCursor cursor = new ParserCursor(0, buffer.length());
245 
246         HttpVersion version = (HttpVersion) parser.parseProtocolVersion(buffer, cursor);
247         Assert.assertEquals("HTTP protocol name", "HTTP", version.getProtocol());
248         Assert.assertEquals("HTTP major version number", 1, version.getMajor());
249         Assert.assertEquals("HTTP minor version number", 1, version.getMinor());
250         Assert.assertEquals("HTTP version number", "HTTP/1.1", version.toString());
251         Assert.assertEquals(buffer.length(), cursor.getPos());
252         Assert.assertTrue(cursor.atEnd());
253 
254         buffer.clear();
255         buffer.append("HTTP/1.123 123");
256         cursor = new ParserCursor(0, buffer.length());
257 
258         version = (HttpVersion) parser.parseProtocolVersion(buffer, cursor);
259         Assert.assertEquals("HTTP protocol name", "HTTP", version.getProtocol());
260         Assert.assertEquals("HTTP major version number", 1, version.getMajor());
261         Assert.assertEquals("HTTP minor version number", 123, version.getMinor());
262         Assert.assertEquals("HTTP version number", "HTTP/1.123", version.toString());
263         Assert.assertEquals(' ', buffer.charAt(cursor.getPos()));
264         Assert.assertEquals(buffer.length() - 4, cursor.getPos());
265         Assert.assertFalse(cursor.atEnd());
266     }
267 
268     @Test
269     public void testInvalidHttpVersionParsing() throws Exception {
270         final CharArrayBuffer buffer = new CharArrayBuffer(16);
271         buffer.clear();
272         buffer.append("    ");
273         ParserCursor cursor = new ParserCursor(0, buffer.length());
274         try {
275             this.parser.parseProtocolVersion(buffer, cursor);
276             Assert.fail("ParseException should have been thrown");
277         } catch (final ParseException e) {
278             //expected
279         }
280         buffer.clear();
281         buffer.append("HTT");
282         cursor = new ParserCursor(0, buffer.length());
283         try {
284             this.parser.parseProtocolVersion(buffer, cursor);
285             Assert.fail("ParseException should have been thrown");
286         } catch (final ParseException e) {
287             //expected
288         }
289         buffer.clear();
290         buffer.append("crap");
291         cursor = new ParserCursor(0, buffer.length());
292         try {
293             this.parser.parseProtocolVersion(buffer, cursor);
294             Assert.fail("ParseException should have been thrown");
295         } catch (final ParseException e) {
296             //expected
297         }
298         buffer.clear();
299         buffer.append("HTTP/crap");
300         cursor = new ParserCursor(0, buffer.length());
301         try {
302             this.parser.parseProtocolVersion(buffer, cursor);
303             Assert.fail("ParseException should have been thrown");
304         } catch (final ParseException e) {
305             //expected
306         }
307         buffer.clear();
308         buffer.append("HTTP/1");
309         cursor = new ParserCursor(0, buffer.length());
310         try {
311             this.parser.parseProtocolVersion(buffer, cursor);
312             Assert.fail("ParseException should have been thrown");
313         } catch (final ParseException e) {
314             //expected
315         }
316         buffer.clear();
317         buffer.append("HTTP/1234");
318         cursor = new ParserCursor(0, buffer.length());
319         try {
320             this.parser.parseProtocolVersion(buffer, cursor);
321             Assert.fail("ParseException should have been thrown");
322         } catch (final ParseException e) {
323             //expected
324         }
325         buffer.clear();
326         buffer.append("HTTP/1.");
327         cursor = new ParserCursor(0, buffer.length());
328         try {
329             this.parser.parseProtocolVersion(buffer, cursor);
330             Assert.fail("ParseException should have been thrown");
331         } catch (final ParseException e) {
332             //expected
333         }
334         buffer.clear();
335         buffer.append("HTTP/whatever.whatever whatever");
336         cursor = new ParserCursor(0, buffer.length());
337         try {
338             this.parser.parseProtocolVersion(buffer, cursor);
339             Assert.fail("ParseException should have been thrown");
340         } catch (final ParseException e) {
341             //expected
342         }
343         buffer.clear();
344         buffer.append("HTTP/1.whatever whatever");
345         cursor = new ParserCursor(0, buffer.length());
346         try {
347             this.parser.parseProtocolVersion(buffer, cursor);
348             Assert.fail("ParseException should have been thrown");
349         } catch (final ParseException e) {
350             //expected
351         }
352     }
353 
354     @Test
355     public void testHeaderParse() throws Exception {
356         final CharArrayBuffer buf = new CharArrayBuffer(64);
357         //typical request line
358         buf.clear();
359         buf.append("header: blah");
360         Header header = this.parser.parseHeader(buf);
361         Assert.assertEquals("header", header.getName());
362         Assert.assertEquals("blah", header.getValue());
363 
364         //Lots of blanks
365         buf.clear();
366         buf.append("    header:    blah    ");
367         header = this.parser.parseHeader(buf);
368         Assert.assertEquals("header", header.getName());
369         Assert.assertEquals("blah", header.getValue());
370     }
371 
372     @Test
373     public void testInvalidHeaderParsing() throws Exception {
374         final CharArrayBuffer buffer = new CharArrayBuffer(16);
375         buffer.clear();
376         buffer.append("");
377         try {
378             this.parser.parseHeader(buffer);
379             Assert.fail("ParseException should have been thrown");
380         } catch (final ParseException e) {
381             //expected
382         }
383         buffer.clear();
384         buffer.append("blah");
385         try {
386             this.parser.parseHeader(buffer);
387             Assert.fail("ParseException should have been thrown");
388         } catch (final ParseException e) {
389             //expected
390         }
391         buffer.clear();
392         buffer.append(":");
393         try {
394             this.parser.parseHeader(buffer);
395             Assert.fail("ParseException should have been thrown");
396         } catch (final ParseException e) {
397             //expected
398         }
399         buffer.clear();
400         buffer.append("   :");
401         try {
402             this.parser.parseHeader(buffer);
403             Assert.fail("ParseException should have been thrown");
404         } catch (final ParseException e) {
405             //expected
406         }
407         buffer.clear();
408         buffer.append(": blah");
409         try {
410             this.parser.parseHeader(buffer);
411             Assert.fail("ParseException should have been thrown");
412         } catch (final ParseException e) {
413             //expected
414         }
415         buffer.clear();
416         buffer.append(" : blah");
417         try {
418             this.parser.parseHeader(buffer);
419             Assert.fail("ParseException should have been thrown");
420         } catch (final ParseException e) {
421             //expected
422         }
423         buffer.clear();
424         buffer.append("header : blah");
425         try {
426             this.parser.parseHeader(buffer);
427             Assert.fail("ParseException should have been thrown");
428         } catch (final ParseException e) {
429             //expected
430         }
431     }
432 
433 }