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