NS-3 based Named Data Networking (NDN) simulator
ndnSIM 2.5: NDN, CCN, CCNx, content centric networks
API Documentation
parser.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2011, Peter Thorson. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are met:
6  * * Redistributions of source code must retain the above copyright
7  * notice, this list of conditions and the following disclaimer.
8  * * Redistributions in binary form must reproduce the above copyright
9  * notice, this list of conditions and the following disclaimer in the
10  * documentation and/or other materials provided with the distribution.
11  * * Neither the name of the WebSocket++ Project nor the
12  * names of its contributors may be used to endorse or promote products
13  * derived from this software without specific prior written permission.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED. IN NO EVENT SHALL PETER THORSON BE LIABLE FOR ANY
19  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
21  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
22  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
24  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25  *
26  */
27 //#define BOOST_TEST_DYN_LINK
28 #define BOOST_TEST_MODULE http_parser
29 #include <boost/test/unit_test.hpp>
30 
31 #include <iostream>
32 #include <string>
33 
36 
38  // Valid characters
39 
40  // misc
41  BOOST_CHECK( websocketpp::http::is_token_char('!') );
42  BOOST_CHECK( websocketpp::http::is_token_char('#') );
43  BOOST_CHECK( websocketpp::http::is_token_char('$') );
44  BOOST_CHECK( websocketpp::http::is_token_char('%') );
45  BOOST_CHECK( websocketpp::http::is_token_char('&') );
46  BOOST_CHECK( websocketpp::http::is_token_char('\'') );
47  BOOST_CHECK( websocketpp::http::is_token_char('*') );
48  BOOST_CHECK( websocketpp::http::is_token_char('+') );
49  BOOST_CHECK( websocketpp::http::is_token_char('-') );
50  BOOST_CHECK( websocketpp::http::is_token_char('.') );
51  BOOST_CHECK( websocketpp::http::is_token_char('^') );
52  BOOST_CHECK( websocketpp::http::is_token_char('_') );
53  BOOST_CHECK( websocketpp::http::is_token_char('`') );
54  BOOST_CHECK( websocketpp::http::is_token_char('~') );
55 
56  // numbers
57  for (int i = 0x30; i < 0x3a; i++) {
58  BOOST_CHECK( websocketpp::http::is_token_char((unsigned char)(i)) );
59  }
60 
61  // upper
62  for (int i = 0x41; i < 0x5b; i++) {
63  BOOST_CHECK( websocketpp::http::is_token_char((unsigned char)(i)) );
64  }
65 
66  // lower
67  for (int i = 0x61; i < 0x7b; i++) {
68  BOOST_CHECK( websocketpp::http::is_token_char((unsigned char)(i)) );
69  }
70 
71  // invalid characters
72 
73  // lower unprintable
74  for (int i = 0; i < 33; i++) {
75  BOOST_CHECK( !websocketpp::http::is_token_char((unsigned char)(i)) );
76  }
77 
78  // misc
79  BOOST_CHECK( !websocketpp::http::is_token_char('(') );
80  BOOST_CHECK( !websocketpp::http::is_token_char(')') );
81  BOOST_CHECK( !websocketpp::http::is_token_char('<') );
82  BOOST_CHECK( !websocketpp::http::is_token_char('>') );
83  BOOST_CHECK( !websocketpp::http::is_token_char('@') );
84  BOOST_CHECK( !websocketpp::http::is_token_char(',') );
85  BOOST_CHECK( !websocketpp::http::is_token_char(';') );
86  BOOST_CHECK( !websocketpp::http::is_token_char(':') );
87  BOOST_CHECK( !websocketpp::http::is_token_char('\\') );
88  BOOST_CHECK( !websocketpp::http::is_token_char('"') );
89  BOOST_CHECK( !websocketpp::http::is_token_char('/') );
90  BOOST_CHECK( !websocketpp::http::is_token_char('[') );
91  BOOST_CHECK( !websocketpp::http::is_token_char(']') );
92  BOOST_CHECK( !websocketpp::http::is_token_char('?') );
93  BOOST_CHECK( !websocketpp::http::is_token_char('=') );
94  BOOST_CHECK( !websocketpp::http::is_token_char('{') );
95  BOOST_CHECK( !websocketpp::http::is_token_char('}') );
96 
97  // upper unprintable and out of ascii range
98  for (int i = 127; i < 256; i++) {
99  BOOST_CHECK( !websocketpp::http::is_token_char((unsigned char)(i)) );
100  }
101 
102  // is not
103  BOOST_CHECK( !websocketpp::http::is_not_token_char('!') );
104  BOOST_CHECK( websocketpp::http::is_not_token_char('(') );
105 }
106 
108  std::string d1 = "foo";
109  std::string d2 = " foo ";
110 
111  std::pair<std::string,std::string::const_iterator> ret;
112 
113  ret = websocketpp::http::parser::extract_token(d1.begin(),d1.end());
114  BOOST_CHECK( ret.first == "foo" );
115  BOOST_CHECK( ret.second == d1.begin()+3 );
116 
117  ret = websocketpp::http::parser::extract_token(d2.begin(),d2.end());
118  BOOST_CHECK( ret.first.empty() );
119  BOOST_CHECK( ret.second == d2.begin()+0 );
120 
121  ret = websocketpp::http::parser::extract_token(d2.begin()+1,d2.end());
122  BOOST_CHECK( ret.first == "foo" );
123  BOOST_CHECK( ret.second == d2.begin()+4 );
124 }
125 
127  std::string d1 = "\"foo\"";
128  std::string d2 = "\"foo\\\"bar\\\"baz\"";
129  std::string d3 = "\"foo\" ";
130  std::string d4;
131  std::string d5 = "foo";
132 
133  std::pair<std::string,std::string::const_iterator> ret;
134 
136 
137  ret = extract_quoted_string(d1.begin(),d1.end());
138  BOOST_CHECK( ret.first == "foo" );
139  BOOST_CHECK( ret.second == d1.end() );
140 
141  ret = extract_quoted_string(d2.begin(),d2.end());
142  BOOST_CHECK( ret.first == "foo\"bar\"baz" );
143  BOOST_CHECK( ret.second == d2.end() );
144 
145  ret = extract_quoted_string(d3.begin(),d3.end());
146  BOOST_CHECK( ret.first == "foo" );
147  BOOST_CHECK( ret.second == d3.begin()+5 );
148 
149  ret = extract_quoted_string(d4.begin(),d4.end());
150  BOOST_CHECK( ret.first.empty() );
151  BOOST_CHECK( ret.second == d4.begin() );
152 
153  ret = extract_quoted_string(d5.begin(),d5.end());
154  BOOST_CHECK( ret.first.empty() );
155  BOOST_CHECK( ret.second == d5.begin() );
156 }
157 
159  std::string d1 = " foo bar";
160  d1.append(1,char(9));
161  d1.append("baz\r\n d\r\n \r\n e\r\nf");
162 
163  std::string::const_iterator ret;
164 
165  ret = websocketpp::http::parser::extract_all_lws(d1.begin(),d1.end());
166  BOOST_CHECK( ret == d1.begin()+1 );
167 
168  ret = websocketpp::http::parser::extract_all_lws(d1.begin()+1,d1.end());
169  BOOST_CHECK( ret == d1.begin()+1 );
170 
171  ret = websocketpp::http::parser::extract_all_lws(d1.begin()+4,d1.end());
172  BOOST_CHECK( ret == d1.begin()+9 );
173 
174  ret = websocketpp::http::parser::extract_all_lws(d1.begin()+12,d1.end());
175  BOOST_CHECK( ret == d1.begin()+13 );
176 
177  ret = websocketpp::http::parser::extract_all_lws(d1.begin()+16,d1.end());
178  BOOST_CHECK( ret == d1.begin()+19 );
179 
180  ret = websocketpp::http::parser::extract_all_lws(d1.begin()+20,d1.end());
181  BOOST_CHECK( ret == d1.begin()+28 );
182 
183  ret = websocketpp::http::parser::extract_all_lws(d1.begin()+29,d1.end());
184  BOOST_CHECK( ret == d1.begin()+29 );
185 }
186 
187 BOOST_AUTO_TEST_CASE( extract_attributes_blank ) {
188  std::string s;
189 
191  std::string::const_iterator it;
192 
193  it = websocketpp::http::parser::extract_attributes(s.begin(),s.end(),a);
194  BOOST_CHECK( it == s.begin() );
195  BOOST_CHECK_EQUAL( a.size(), 0 );
196 }
197 
198 BOOST_AUTO_TEST_CASE( extract_attributes_simple ) {
199  std::string s = "foo";
200 
202  std::string::const_iterator it;
203 
204  it = websocketpp::http::parser::extract_attributes(s.begin(),s.end(),a);
205  BOOST_CHECK( it == s.end() );
206  BOOST_CHECK_EQUAL( a.size(), 1 );
207  BOOST_CHECK( a.find("foo") != a.end() );
208  BOOST_CHECK_EQUAL( a.find("foo")->second, "" );
209 }
210 
212  std::string s1;
213  std::string s2 = "foo";
214  std::string s3 = " foo \r\nAbc";
215  std::string s4 = " \r\n foo ";
216  std::string s5 = "foo,bar";
217  std::string s6 = "foo;bar";
218  std::string s7 = "foo;baz,bar";
219  std::string s8 = "foo;bar;baz";
220  std::string s9 = "foo;bar=baz";
221  std::string s10 = "foo;bar=baz;boo";
222  std::string s11 = "foo;bar=baz;boo,bob";
223  std::string s12 = "foo;bar=\"a b c\"";
224  std::string s13 = "foo;bar=\"a \\\"b\\\" c\"";
225 
226 
227  std::string sx = "foo;bar=\"a \\\"b\\\" c\"";
230  std::string::const_iterator it;
231 
233 
234  it = extract_parameters(s1.begin(),s1.end(),p);
235  BOOST_CHECK( it == s1.begin() );
236 
237  p.clear();
238  it = extract_parameters(s2.begin(),s2.end(),p);
239  BOOST_CHECK( it == s2.end() );
240  BOOST_CHECK_EQUAL( p.size(), 1 );
241  BOOST_CHECK( p[0].first == "foo" );
242  BOOST_CHECK_EQUAL( p[0].second.size(), 0 );
243 
244  p.clear();
245  it = extract_parameters(s3.begin(),s3.end(),p);
246  BOOST_CHECK( it == s3.begin()+5 );
247  BOOST_CHECK_EQUAL( p.size(), 1 );
248  BOOST_CHECK( p[0].first == "foo" );
249  BOOST_CHECK_EQUAL( p[0].second.size(), 0 );
250 
251  p.clear();
252  it = extract_parameters(s4.begin(),s4.end(),p);
253  BOOST_CHECK( it == s4.end() );
254  BOOST_CHECK_EQUAL( p.size(), 1 );
255  BOOST_CHECK( p[0].first == "foo" );
256  BOOST_CHECK_EQUAL( p[0].second.size(), 0 );
257 
258  p.clear();
259  it = extract_parameters(s5.begin(),s5.end(),p);
260  BOOST_CHECK( it == s5.end() );
261  BOOST_CHECK_EQUAL( p.size(), 2 );
262  BOOST_CHECK( p[0].first == "foo" );
263  BOOST_CHECK_EQUAL( p[0].second.size(), 0 );
264  BOOST_CHECK( p[1].first == "bar" );
265  BOOST_CHECK_EQUAL( p[1].second.size(), 0 );
266 
267  p.clear();
268  it = extract_parameters(s6.begin(),s6.end(),p);
269  BOOST_CHECK( it == s6.end() );
270  BOOST_CHECK_EQUAL( p.size(), 1 );
271  BOOST_CHECK( p[0].first == "foo" );
272  a = p[0].second;
273  BOOST_CHECK_EQUAL( a.size(), 1 );
274  BOOST_CHECK( a.find("bar") != a.end() );
275  BOOST_CHECK_EQUAL( a.find("bar")->second, "" );
276 
277  p.clear();
278  it = extract_parameters(s7.begin(),s7.end(),p);
279  BOOST_CHECK( it == s7.end() );
280  BOOST_CHECK_EQUAL( p.size(), 2 );
281  BOOST_CHECK( p[0].first == "foo" );
282  a = p[0].second;
283  BOOST_CHECK_EQUAL( a.size(), 1 );
284  BOOST_CHECK( a.find("baz") != a.end() );
285  BOOST_CHECK_EQUAL( a.find("baz")->second, "" );
286  BOOST_CHECK( p[1].first == "bar" );
287  a = p[1].second;
288  BOOST_CHECK_EQUAL( a.size(), 0 );
289 
290  p.clear();
291  it = extract_parameters(s8.begin(),s8.end(),p);
292  BOOST_CHECK( it == s8.end() );
293  BOOST_CHECK_EQUAL( p.size(), 1 );
294  BOOST_CHECK( p[0].first == "foo" );
295  a = p[0].second;
296  BOOST_CHECK_EQUAL( a.size(), 2 );
297  BOOST_CHECK( a.find("bar") != a.end() );
298  BOOST_CHECK_EQUAL( a.find("bar")->second, "" );
299  BOOST_CHECK( a.find("baz") != a.end() );
300  BOOST_CHECK_EQUAL( a.find("baz")->second, "" );
301 
302  p.clear();
303  it = extract_parameters(s9.begin(),s9.end(),p);
304  BOOST_CHECK( it == s9.end() );
305  BOOST_CHECK_EQUAL( p.size(), 1 );
306  BOOST_CHECK( p[0].first == "foo" );
307  a = p[0].second;
308  BOOST_CHECK_EQUAL( a.size(), 1 );
309  BOOST_CHECK( a.find("bar") != a.end() );
310  BOOST_CHECK_EQUAL( a.find("bar")->second, "baz" );
311 
312  p.clear();
313  it = extract_parameters(s10.begin(),s10.end(),p);
314  BOOST_CHECK( it == s10.end() );
315  BOOST_CHECK_EQUAL( p.size(), 1 );
316  BOOST_CHECK( p[0].first == "foo" );
317  a = p[0].second;
318  BOOST_CHECK_EQUAL( a.size(), 2 );
319  BOOST_CHECK( a.find("bar") != a.end() );
320  BOOST_CHECK_EQUAL( a.find("bar")->second, "baz" );
321  BOOST_CHECK( a.find("boo") != a.end() );
322  BOOST_CHECK_EQUAL( a.find("boo")->second, "" );
323 
324  p.clear();
325  it = extract_parameters(s11.begin(),s11.end(),p);
326  BOOST_CHECK( it == s11.end() );
327  BOOST_CHECK_EQUAL( p.size(), 2 );
328  BOOST_CHECK( p[0].first == "foo" );
329  a = p[0].second;
330  BOOST_CHECK_EQUAL( a.size(), 2 );
331  BOOST_CHECK( a.find("bar") != a.end() );
332  BOOST_CHECK_EQUAL( a.find("bar")->second, "baz" );
333  BOOST_CHECK( a.find("boo") != a.end() );
334  BOOST_CHECK_EQUAL( a.find("boo")->second, "" );
335  a = p[1].second;
336  BOOST_CHECK_EQUAL( a.size(), 0 );
337 
338  p.clear();
339  it = extract_parameters(s12.begin(),s12.end(),p);
340  BOOST_CHECK( it == s12.end() );
341  BOOST_CHECK_EQUAL( p.size(), 1 );
342  BOOST_CHECK( p[0].first == "foo" );
343  a = p[0].second;
344  BOOST_CHECK_EQUAL( a.size(), 1 );
345  BOOST_CHECK( a.find("bar") != a.end() );
346  BOOST_CHECK_EQUAL( a.find("bar")->second, "a b c" );
347 
348  p.clear();
349  it = extract_parameters(s13.begin(),s13.end(),p);
350  BOOST_CHECK( it == s13.end() );
351  BOOST_CHECK_EQUAL( p.size(), 1 );
352  BOOST_CHECK( p[0].first == "foo" );
353  a = p[0].second;
354  BOOST_CHECK_EQUAL( a.size(), 1 );
355  BOOST_CHECK( a.find("bar") != a.end() );
356  BOOST_CHECK_EQUAL( a.find("bar")->second, "a \"b\" c" );
357 }
358 
360  std::string test1 = "foo";
361  std::string test2 = " foo ";
362  std::string test3 = "foo ";
363  std::string test4 = " foo";
364  std::string test5 = " foo ";
365  std::string test6 = " \r\n foo ";
366  std::string test7 = " \t foo ";
367  std::string test8 = " \t ";
368  std::string test9 = " \n\r";
369 
370  BOOST_CHECK_EQUAL( websocketpp::http::parser::strip_lws(test1), "foo" );
371  BOOST_CHECK_EQUAL( websocketpp::http::parser::strip_lws(test2), "foo" );
372  BOOST_CHECK_EQUAL( websocketpp::http::parser::strip_lws(test3), "foo" );
373  BOOST_CHECK_EQUAL( websocketpp::http::parser::strip_lws(test4), "foo" );
374  BOOST_CHECK_EQUAL( websocketpp::http::parser::strip_lws(test5), "foo" );
375  BOOST_CHECK_EQUAL( websocketpp::http::parser::strip_lws(test6), "foo" );
376  BOOST_CHECK_EQUAL( websocketpp::http::parser::strip_lws(test7), "foo" );
377  BOOST_CHECK_EQUAL( websocketpp::http::parser::strip_lws(test8), "" );
378  BOOST_CHECK_EQUAL( websocketpp::http::parser::strip_lws(test9), "" );
379 }
380 
381 BOOST_AUTO_TEST_CASE( case_insensitive_headers ) {
383 
384  r.replace_header("foo","bar");
385 
386  BOOST_CHECK_EQUAL( r.get_header("foo"), "bar" );
387  BOOST_CHECK_EQUAL( r.get_header("FOO"), "bar" );
388  BOOST_CHECK_EQUAL( r.get_header("Foo"), "bar" );
389 }
390 
391 BOOST_AUTO_TEST_CASE( case_insensitive_headers_overwrite ) {
393 
394  r.replace_header("foo","bar");
395 
396  BOOST_CHECK_EQUAL( r.get_header("foo"), "bar" );
397  BOOST_CHECK_EQUAL( r.get_header("Foo"), "bar" );
398 
399  r.replace_header("Foo","baz");
400 
401  BOOST_CHECK_EQUAL( r.get_header("foo"), "baz" );
402  BOOST_CHECK_EQUAL( r.get_header("Foo"), "baz" );
403 
404  r.remove_header("FoO");
405 
406  BOOST_CHECK_EQUAL( r.get_header("foo"), "" );
407  BOOST_CHECK_EQUAL( r.get_header("Foo"), "" );
408 }
409 
410 BOOST_AUTO_TEST_CASE( blank_consume ) {
412 
413  std::string raw;
414 
415  bool exception = false;
416 
417  try {
418  r.consume(raw.c_str(),raw.size());
419  } catch (...) {
420  exception = true;
421  }
422 
423  BOOST_CHECK( exception == false );
424  BOOST_CHECK( r.ready() == false );
425 }
426 
427 BOOST_AUTO_TEST_CASE( blank_request ) {
429 
430  std::string raw = "\r\n\r\n";
431 
432  bool exception = false;
433 
434  try {
435  r.consume(raw.c_str(),raw.size());
436  } catch (...) {
437  exception = true;
438  }
439 
440  BOOST_CHECK( exception == true );
441  BOOST_CHECK( r.ready() == false );
442 }
443 
444 BOOST_AUTO_TEST_CASE( bad_request_no_host ) {
446 
447  std::string raw = "GET / HTTP/1.1\r\n\r\n";
448 
449  bool exception = false;
450 
451  try {
452  r.consume(raw.c_str(),raw.size());
453  } catch (...) {
454  exception = true;
455  }
456 
457  BOOST_CHECK( exception == true );
458  BOOST_CHECK( r.ready() == false );
459 }
460 
461 BOOST_AUTO_TEST_CASE( basic_request ) {
463 
464  std::string raw = "GET / HTTP/1.1\r\nHost: www.example.com\r\n\r\n";
465 
466  bool exception = false;
467  size_t pos = 0;
468 
469  try {
470  pos = r.consume(raw.c_str(),raw.size());
471  } catch (std::exception &e) {
472  exception = true;
473  std::cout << e.what() << std::endl;
474  }
475 
476  BOOST_CHECK( exception == false );
477  BOOST_CHECK( pos == 41 );
478  BOOST_CHECK( r.ready() == true );
479  BOOST_CHECK( r.get_version() == "HTTP/1.1" );
480  BOOST_CHECK( r.get_method() == "GET" );
481  BOOST_CHECK( r.get_uri() == "/" );
482  BOOST_CHECK( r.get_header("Host") == "www.example.com" );
483 }
484 
485 BOOST_AUTO_TEST_CASE( basic_request_with_body ) {
487 
488  std::string raw = "GET / HTTP/1.1\r\nHost: www.example.com\r\nContent-Length: 5\r\n\r\nabcdef";
489 
490  bool exception = false;
491  size_t pos = 0;
492 
493  try {
494  pos = r.consume(raw.c_str(),raw.size());
495  } catch (std::exception &e) {
496  exception = true;
497  std::cout << e.what() << std::endl;
498  }
499 
500  BOOST_CHECK( exception == false );
501  BOOST_CHECK_EQUAL( pos, 65 );
502  BOOST_CHECK( r.ready() == true );
503  BOOST_CHECK_EQUAL( r.get_version(), "HTTP/1.1" );
504  BOOST_CHECK_EQUAL( r.get_method(), "GET" );
505  BOOST_CHECK_EQUAL( r.get_uri(), "/" );
506  BOOST_CHECK_EQUAL( r.get_header("Host"), "www.example.com" );
507  BOOST_CHECK_EQUAL( r.get_header("Content-Length"), "5" );
508  BOOST_CHECK_EQUAL( r.get_body(), "abcde" );
509 
510  BOOST_CHECK_EQUAL( r.get_headers().size(), 2);
511 
512  websocketpp::http::parser::header_list::const_iterator it = r.get_headers().begin();
513 
514  BOOST_CHECK_EQUAL( it->first, "Content-Length");
515  BOOST_CHECK_EQUAL( it->second, "5");
516 
517  it++;
518 
519  BOOST_CHECK_EQUAL( it->first, "Host");
520  BOOST_CHECK_EQUAL( it->second, "www.example.com");
521 }
522 
523 BOOST_AUTO_TEST_CASE( basic_request_with_body_split ) {
525 
526  std::string raw = "GET / HTTP/1.1\r\nHost: www.example.com\r\nContent-Length: 6\r\n\r\nabc";
527  std::string raw2 = "def";
528 
529  bool exception = false;
530  size_t pos = 0;
531 
532  try {
533  pos += r.consume(raw.c_str(),raw.size());
534  pos += r.consume(raw2.c_str(),raw2.size());
535  } catch (std::exception &e) {
536  exception = true;
537  std::cout << e.what() << std::endl;
538  }
539 
540  BOOST_CHECK( exception == false );
541  BOOST_CHECK_EQUAL( pos, 66 );
542  BOOST_CHECK( r.ready() == true );
543  BOOST_CHECK_EQUAL( r.get_version(), "HTTP/1.1" );
544  BOOST_CHECK_EQUAL( r.get_method(), "GET" );
545  BOOST_CHECK_EQUAL( r.get_uri(), "/" );
546  BOOST_CHECK_EQUAL( r.get_header("Host"), "www.example.com" );
547  BOOST_CHECK_EQUAL( r.get_header("Content-Length"), "6" );
548  BOOST_CHECK_EQUAL( r.get_body(), "abcdef" );
549 }
550 
551 
552 
553 BOOST_AUTO_TEST_CASE( trailing_body_characters ) {
555 
556  std::string raw = "GET / HTTP/1.1\r\nHost: www.example.com\r\n\r\na";
557 
558  bool exception = false;
559  size_t pos = 0;
560 
561  try {
562  pos = r.consume(raw.c_str(),raw.size());
563  } catch (...) {
564  exception = true;
565  }
566 
567  BOOST_CHECK( exception == false );
568  BOOST_CHECK( pos == 41 );
569  BOOST_CHECK( r.ready() == true );
570  BOOST_CHECK( r.get_version() == "HTTP/1.1" );
571  BOOST_CHECK( r.get_method() == "GET" );
572  BOOST_CHECK( r.get_uri() == "/" );
573  BOOST_CHECK( r.get_header("Host") == "www.example.com" );
574 }
575 
576 BOOST_AUTO_TEST_CASE( trailing_body_characters_beyond_max_lenth ) {
578 
579  std::string raw = "GET / HTTP/1.1\r\nHost: www.example.com\r\n\r\n";
580  raw.append(websocketpp::http::max_header_size,'*');
581 
582  bool exception = false;
583  size_t pos = 0;
584 
585  try {
586  pos = r.consume(raw.c_str(),raw.size());
587  } catch (...) {
588  exception = true;
589  }
590 
591  BOOST_CHECK( exception == false );
592  BOOST_CHECK( pos == 41 );
593  BOOST_CHECK( r.ready() == true );
594  BOOST_CHECK( r.get_version() == "HTTP/1.1" );
595  BOOST_CHECK( r.get_method() == "GET" );
596  BOOST_CHECK( r.get_uri() == "/" );
597  BOOST_CHECK( r.get_header("Host") == "www.example.com" );
598 }
599 
600 BOOST_AUTO_TEST_CASE( basic_split1 ) {
602 
603  std::string raw = "GET / HTTP/1.1\r\n";
604  std::string raw2 = "Host: www.example.com\r\n\r\na";
605 
606  bool exception = false;
607  size_t pos = 0;
608 
609  try {
610  pos += r.consume(raw.c_str(),raw.size());
611  pos += r.consume(raw2.c_str(),raw2.size());
612  } catch (std::exception &e) {
613  exception = true;
614  std::cout << e.what() << std::endl;
615  }
616 
617  BOOST_CHECK( exception == false );
618  BOOST_CHECK( pos == 41 );
619  BOOST_CHECK( r.ready() == true );
620  BOOST_CHECK( r.get_version() == "HTTP/1.1" );
621  BOOST_CHECK( r.get_method() == "GET" );
622  BOOST_CHECK( r.get_uri() == "/" );
623  BOOST_CHECK( r.get_header("Host") == "www.example.com" );
624 }
625 
626 BOOST_AUTO_TEST_CASE( basic_split2 ) {
628 
629  std::string raw = "GET / HTTP/1.1\r\nHost: www.example.com\r";
630  std::string raw2 = "\n\r\na";
631 
632  bool exception = false;
633  size_t pos = 0;
634 
635  try {
636  pos += r.consume(raw.c_str(),raw.size());
637  pos += r.consume(raw2.c_str(),raw2.size());
638  } catch (std::exception &e) {
639  exception = true;
640  std::cout << e.what() << std::endl;
641  }
642 
643  BOOST_CHECK( exception == false );
644  BOOST_CHECK( pos == 41 );
645  BOOST_CHECK( r.ready() == true );
646  BOOST_CHECK( r.get_version() == "HTTP/1.1" );
647  BOOST_CHECK( r.get_method() == "GET" );
648  BOOST_CHECK( r.get_uri() == "/" );
649  BOOST_CHECK( r.get_header("Host") == "www.example.com" );
650 }
651 
652 BOOST_AUTO_TEST_CASE( max_header_len ) {
654 
655  std::string raw(websocketpp::http::max_header_size-1,'*');
656  raw += "\r\n";
657 
658  bool exception = false;
659  size_t pos = 0;
660 
661  try {
662  pos += r.consume(raw.c_str(),raw.size());
663  } catch (const websocketpp::http::exception& e) {
665  exception = true;
666  }
667  }
668 
669  BOOST_CHECK( exception == true );
670 }
671 
672 BOOST_AUTO_TEST_CASE( max_header_len_split ) {
674 
675  std::string raw(websocketpp::http::max_header_size-1,'*');
676  std::string raw2(2,'*');
677 
678  bool exception = false;
679  size_t pos = 0;
680 
681  try {
682  pos += r.consume(raw.c_str(),raw.size());
683  pos += r.consume(raw2.c_str(),raw2.size());
684  } catch (const websocketpp::http::exception& e) {
686  exception = true;
687  }
688  }
689 
690  BOOST_CHECK( exception == true );
691 }
692 
693 BOOST_AUTO_TEST_CASE( max_body_len ) {
695 
696  r.set_max_body_size(5);
697 
698  std::string raw = "GET / HTTP/1.1\r\nHost: www.example.com\r\nContent-Length: 6\r\n\r\nabcdef";
699 
700  bool exception = false;
701  size_t pos = 0;
702 
703  try {
704  pos += r.consume(raw.c_str(),raw.size());
705  } catch (websocketpp::http::exception const & e) {
706  exception = true;
708  }
709 
710  BOOST_CHECK_EQUAL(r.get_max_body_size(),5);
711  BOOST_CHECK( exception == true );
712 }
713 
714 BOOST_AUTO_TEST_CASE( firefox_full_request ) {
716 
717  std::string raw = "GET / HTTP/1.1\r\nHost: localhost:5000\r\nUser-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.7; rv:10.0) Gecko/20100101 Firefox/10.0\r\nAccept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\nAccept-Language: en-us,en;q=0.5\r\nAccept-Encoding: gzip, deflate\r\nConnection: keep-alive, Upgrade\r\nSec-WebSocket-Version: 8\r\nSec-WebSocket-Origin: http://zaphoyd.com\r\nSec-WebSocket-Key: pFik//FxwFk0riN4ZiPFjQ==\r\nPragma: no-cache\r\nCache-Control: no-cache\r\nUpgrade: websocket\r\n\r\n";
718 
719  bool exception = false;
720  size_t pos = 0;
721 
722  try {
723  pos += r.consume(raw.c_str(),raw.size());
724  } catch (...) {
725  exception = true;
726  }
727 
728  BOOST_CHECK( exception == false );
729  BOOST_CHECK( pos == 482 );
730  BOOST_CHECK( r.ready() == true );
731  BOOST_CHECK( r.get_version() == "HTTP/1.1" );
732  BOOST_CHECK( r.get_method() == "GET" );
733  BOOST_CHECK( r.get_uri() == "/" );
734  BOOST_CHECK( r.get_header("Host") == "localhost:5000" );
735  BOOST_CHECK( r.get_header("User-Agent") == "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.7; rv:10.0) Gecko/20100101 Firefox/10.0" );
736  BOOST_CHECK( r.get_header("Accept") == "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8" );
737  BOOST_CHECK( r.get_header("Accept-Language") == "en-us,en;q=0.5" );
738  BOOST_CHECK( r.get_header("Accept-Encoding") == "gzip, deflate" );
739  BOOST_CHECK( r.get_header("Connection") == "keep-alive, Upgrade" );
740  BOOST_CHECK( r.get_header("Sec-WebSocket-Version") == "8" );
741  BOOST_CHECK( r.get_header("Sec-WebSocket-Origin") == "http://zaphoyd.com" );
742  BOOST_CHECK( r.get_header("Sec-WebSocket-Key") == "pFik//FxwFk0riN4ZiPFjQ==" );
743  BOOST_CHECK( r.get_header("Pragma") == "no-cache" );
744  BOOST_CHECK( r.get_header("Cache-Control") == "no-cache" );
745  BOOST_CHECK( r.get_header("Upgrade") == "websocket" );
746 }
747 
748 BOOST_AUTO_TEST_CASE( bad_method ) {
750 
751  std::string raw = "GE]T / HTTP/1.1\r\nHost: www.example.com\r\n\r\n";
752 
753  bool exception = false;
754 
755  try {
756  r.consume(raw.c_str(),raw.size());
757  } catch (...) {
758  exception = true;
759  }
760 
761  BOOST_CHECK( exception == true );
762 }
763 
764 BOOST_AUTO_TEST_CASE( bad_header_name ) {
766 
767  std::string raw = "GET / HTTP/1.1\r\nHo]st: www.example.com\r\n\r\n";
768 
769  bool exception = false;
770 
771  try {
772  r.consume(raw.c_str(),raw.size());
773  } catch (...) {
774  exception = true;
775  }
776 
777  BOOST_CHECK( exception == true );
778 }
779 
780 BOOST_AUTO_TEST_CASE( old_http_version ) {
782 
783  std::string raw = "GET / HTTP/1.0\r\nHost: www.example.com\r\n\r\n";
784 
785  bool exception = false;
786  size_t pos = 0;
787 
788  try {
789  pos = r.consume(raw.c_str(),raw.size());
790  } catch (...) {
791  exception = true;
792  }
793 
794  BOOST_CHECK( exception == false );
795  BOOST_CHECK_EQUAL( pos, 41 );
796  BOOST_CHECK( r.ready() == true );
797  BOOST_CHECK_EQUAL( r.get_version(), "HTTP/1.0" );
798  BOOST_CHECK_EQUAL( r.get_method(), "GET" );
799  BOOST_CHECK_EQUAL( r.get_uri(), "/" );
800  BOOST_CHECK_EQUAL( r.get_header("Host"), "www.example.com" );
801 }
802 
803 BOOST_AUTO_TEST_CASE( new_http_version1 ) {
805 
806  std::string raw = "GET / HTTP/1.12\r\nHost: www.example.com\r\n\r\n";
807 
808  bool exception = false;
809  size_t pos = 0;
810 
811  try {
812  pos = r.consume(raw.c_str(),raw.size());
813  } catch (...) {
814  exception = true;
815  }
816 
817  BOOST_CHECK( exception == false );
818  BOOST_CHECK_EQUAL( pos, 42 );
819  BOOST_CHECK( r.ready() == true );
820  BOOST_CHECK_EQUAL( r.get_version(), "HTTP/1.12" );
821  BOOST_CHECK_EQUAL( r.get_method(), "GET" );
822  BOOST_CHECK_EQUAL( r.get_uri(), "/" );
823  BOOST_CHECK_EQUAL( r.get_header("Host"), "www.example.com" );
824 }
825 
826 BOOST_AUTO_TEST_CASE( new_http_version2 ) {
828 
829  std::string raw = "GET / HTTP/12.12\r\nHost: www.example.com\r\n\r\n";
830 
831  bool exception = false;
832  size_t pos = 0;
833 
834  try {
835  pos = r.consume(raw.c_str(),raw.size());
836  } catch (...) {
837  exception = true;
838  }
839 
840  BOOST_CHECK( exception == false );
841  BOOST_CHECK_EQUAL( pos, 43 );
842  BOOST_CHECK( r.ready() == true );
843  BOOST_CHECK_EQUAL( r.get_version(), "HTTP/12.12" );
844  BOOST_CHECK_EQUAL( r.get_method(), "GET" );
845  BOOST_CHECK_EQUAL( r.get_uri(), "/" );
846  BOOST_CHECK_EQUAL( r.get_header("Host"), "www.example.com" );
847 }
848 
849 /* commented out due to not being implemented yet
850 
851 BOOST_AUTO_TEST_CASE( new_http_version3 ) {
852  websocketpp::http::parser::request r;
853 
854  std::string raw = "GET / HTTPS/12.12\r\nHost: www.example.com\r\n\r\n";
855 
856  bool exception = false;
857  size_t pos = 0;
858 
859  try {
860  pos = r.consume(raw.c_str(),raw.size());
861  } catch (...) {
862  exception = true;
863  }
864 
865  BOOST_CHECK( exception == true );
866 }*/
867 
868 BOOST_AUTO_TEST_CASE( header_whitespace1 ) {
870 
871  std::string raw = "GET / HTTP/1.1\r\nHost: www.example.com \r\n\r\n";
872 
873  bool exception = false;
874  size_t pos = 0;
875 
876  try {
877  pos = r.consume(raw.c_str(),raw.size());
878  } catch (...) {
879  exception = true;
880  }
881 
882  BOOST_CHECK( exception == false );
883  BOOST_CHECK_EQUAL( pos, 43 );
884  BOOST_CHECK( r.ready() == true );
885  BOOST_CHECK_EQUAL( r.get_version(), "HTTP/1.1" );
886  BOOST_CHECK_EQUAL( r.get_method(), "GET" );
887  BOOST_CHECK_EQUAL( r.get_uri(), "/" );
888  BOOST_CHECK_EQUAL( r.get_header("Host"), "www.example.com" );
889 }
890 
891 BOOST_AUTO_TEST_CASE( header_whitespace2 ) {
893 
894  std::string raw = "GET / HTTP/1.1\r\nHost:www.example.com\r\n\r\n";
895 
896  bool exception = false;
897  size_t pos = 0;
898 
899  try {
900  pos = r.consume(raw.c_str(),raw.size());
901  } catch (...) {
902  exception = true;
903  }
904 
905  BOOST_CHECK( exception == false );
906  BOOST_CHECK_EQUAL( pos, 40 );
907  BOOST_CHECK( r.ready() == true );
908  BOOST_CHECK_EQUAL( r.get_version(), "HTTP/1.1" );
909  BOOST_CHECK_EQUAL( r.get_method(), "GET" );
910  BOOST_CHECK_EQUAL( r.get_uri(), "/" );
911  BOOST_CHECK_EQUAL( r.get_header("Host"), "www.example.com" );
912 }
913 
914 BOOST_AUTO_TEST_CASE( header_aggregation ) {
916 
917  std::string raw = "GET / HTTP/1.1\r\nHost: www.example.com\r\nFoo: bar\r\nFoo: bat\r\n\r\n";
918 
919  bool exception = false;
920  size_t pos = 0;
921 
922  try {
923  pos = r.consume(raw.c_str(),raw.size());
924  } catch (...) {
925  exception = true;
926  }
927 
928  BOOST_CHECK( exception == false );
929  BOOST_CHECK_EQUAL( pos, 61 );
930  BOOST_CHECK( r.ready() == true );
931  BOOST_CHECK_EQUAL( r.get_version(), "HTTP/1.1" );
932  BOOST_CHECK_EQUAL( r.get_method(), "GET" );
933  BOOST_CHECK_EQUAL( r.get_uri(), "/" );
934  BOOST_CHECK_EQUAL( r.get_header("Foo"), "bar, bat" );
935 }
936 
937 BOOST_AUTO_TEST_CASE( wikipedia_example_response ) {
939 
940  std::string raw = "HTTP/1.1 101 Switching Protocols\r\nUpgrade: websocket\r\nConnection: Upgrade\r\nSec-WebSocket-Accept: HSmrc0sMlYUkAGmm5OPpG2HaGWk=\r\nSec-WebSocket-Protocol: chat\r\n\r\n";
941 
942  bool exception = false;
943  size_t pos = 0;
944 
945  try {
946  pos += r.consume(raw.c_str(),raw.size());
947  } catch (std::exception &e) {
948  exception = true;
949  std::cout << e.what() << std::endl;
950  }
951 
952  BOOST_CHECK( exception == false );
953  BOOST_CHECK_EQUAL( pos, 159 );
954  BOOST_CHECK( r.headers_ready() == true );
955  BOOST_CHECK_EQUAL( r.get_version(), "HTTP/1.1" );
957  BOOST_CHECK_EQUAL( r.get_status_msg(), "Switching Protocols" );
958  BOOST_CHECK_EQUAL( r.get_header("Upgrade"), "websocket" );
959  BOOST_CHECK_EQUAL( r.get_header("Connection"), "Upgrade" );
960  BOOST_CHECK_EQUAL( r.get_header("Sec-WebSocket-Accept"), "HSmrc0sMlYUkAGmm5OPpG2HaGWk=" );
961  BOOST_CHECK_EQUAL( r.get_header("Sec-WebSocket-Protocol"), "chat" );
962 }
963 
964 BOOST_AUTO_TEST_CASE( wikipedia_example_response_trailing ) {
966 
967  std::string raw = "HTTP/1.1 101 Switching Protocols\r\nUpgrade: websocket\r\nConnection: Upgrade\r\nSec-WebSocket-Accept: HSmrc0sMlYUkAGmm5OPpG2HaGWk=\r\nSec-WebSocket-Protocol: chat\r\n\r\n";
968  raw += "a";
969 
970  bool exception = false;
971  size_t pos = 0;
972 
973  try {
974  pos += r.consume(raw.c_str(),raw.size());
975  } catch (std::exception &e) {
976  exception = true;
977  std::cout << e.what() << std::endl;
978  }
979 
980  BOOST_CHECK( exception == false );
981  BOOST_CHECK_EQUAL( pos, 159 );
982  BOOST_CHECK( r.headers_ready() == true );
983  BOOST_CHECK_EQUAL( r.get_version(), "HTTP/1.1" );
985  BOOST_CHECK_EQUAL( r.get_status_msg(), "Switching Protocols" );
986  BOOST_CHECK_EQUAL( r.get_header("Upgrade"), "websocket" );
987  BOOST_CHECK_EQUAL( r.get_header("Connection"), "Upgrade" );
988  BOOST_CHECK_EQUAL( r.get_header("Sec-WebSocket-Accept"), "HSmrc0sMlYUkAGmm5OPpG2HaGWk=" );
989  BOOST_CHECK_EQUAL( r.get_header("Sec-WebSocket-Protocol"), "chat" );
990 }
991 
992 BOOST_AUTO_TEST_CASE( wikipedia_example_response_trailing_large ) {
994 
995  std::string raw = "HTTP/1.1 101 Switching Protocols\r\nUpgrade: websocket\r\nConnection: Upgrade\r\nSec-WebSocket-Accept: HSmrc0sMlYUkAGmm5OPpG2HaGWk=\r\nSec-WebSocket-Protocol: chat\r\n\r\n";
996  raw.append(websocketpp::http::max_header_size,'*');
997 
998  bool exception = false;
999  size_t pos = 0;
1000 
1001  try {
1002  pos += r.consume(raw.c_str(),raw.size());
1003  } catch (std::exception &e) {
1004  exception = true;
1005  std::cout << e.what() << std::endl;
1006  }
1007 
1008  BOOST_CHECK( exception == false );
1009  BOOST_CHECK_EQUAL( pos, 159 );
1010  BOOST_CHECK( r.headers_ready() == true );
1011  BOOST_CHECK_EQUAL( r.get_version(), "HTTP/1.1" );
1013  BOOST_CHECK_EQUAL( r.get_status_msg(), "Switching Protocols" );
1014  BOOST_CHECK_EQUAL( r.get_header("Upgrade"), "websocket" );
1015  BOOST_CHECK_EQUAL( r.get_header("Connection"), "Upgrade" );
1016  BOOST_CHECK_EQUAL( r.get_header("Sec-WebSocket-Accept"), "HSmrc0sMlYUkAGmm5OPpG2HaGWk=" );
1017  BOOST_CHECK_EQUAL( r.get_header("Sec-WebSocket-Protocol"), "chat" );
1018 }
1019 
1020 BOOST_AUTO_TEST_CASE( response_with_non_standard_lws ) {
1022 
1023  std::string raw = "HTTP/1.1 101 Switching Protocols\r\nUpgrade: websocket\r\nConnection: Upgrade\r\nSec-WebSocket-Accept:HSmrc0sMlYUkAGmm5OPpG2HaGWk=\r\nSec-WebSocket-Protocol: chat\r\n\r\n";
1024 
1025  bool exception = false;
1026  size_t pos = 0;
1027 
1028  try {
1029  pos += r.consume(raw.c_str(),raw.size());
1030  } catch (std::exception &e) {
1031  exception = true;
1032  std::cout << e.what() << std::endl;
1033  }
1034 
1035  BOOST_CHECK( exception == false );
1036  BOOST_CHECK_EQUAL( pos, 158 );
1037  BOOST_CHECK( r.headers_ready() );
1038  BOOST_CHECK_EQUAL( r.get_version(), "HTTP/1.1" );
1040  BOOST_CHECK_EQUAL( r.get_status_msg(), "Switching Protocols" );
1041  BOOST_CHECK_EQUAL( r.get_header("Upgrade"), "websocket" );
1042  BOOST_CHECK_EQUAL( r.get_header("Connection"), "Upgrade" );
1043  BOOST_CHECK_EQUAL( r.get_header("Sec-WebSocket-Accept"), "HSmrc0sMlYUkAGmm5OPpG2HaGWk=" );
1044  BOOST_CHECK_EQUAL( r.get_header("Sec-WebSocket-Protocol"), "chat" );
1045 }
1046 
1047 BOOST_AUTO_TEST_CASE( plain_http_response ) {
1049 
1050  std::string raw = "HTTP/1.1 200 OK\r\nDate: Thu, 10 May 2012 11:59:25 GMT\r\nServer: Apache/2.2.21 (Unix) mod_ssl/2.2.21 OpenSSL/0.9.8r DAV/2 PHP/5.3.8 with Suhosin-Patch\r\nLast-Modified: Tue, 30 Mar 2010 17:41:28 GMT\r\nETag: \"16799d-55-4830823a78200\"\r\nAccept-Ranges: bytes\r\nContent-Length: 85\r\nVary: Accept-Encoding\r\nContent-Type: text/html\r\n\r\n<!doctype html>\n<html>\n<head>\n<title>Thor</title>\n</head>\n<body> \n<p>Thor</p>\n</body>";
1051 
1052  bool exception = false;
1053  size_t pos = 0;
1054 
1055  try {
1056  pos += r.consume(raw.c_str(),raw.size());
1057  } catch (std::exception &e) {
1058  exception = true;
1059  std::cout << e.what() << std::endl;
1060  }
1061 
1062  BOOST_CHECK( exception == false );
1063  BOOST_CHECK_EQUAL( pos, 405 );
1064  BOOST_CHECK( r.headers_ready() == true );
1065  BOOST_CHECK( r.ready() == true );
1066  BOOST_CHECK_EQUAL( r.get_version(), "HTTP/1.1" );
1067  BOOST_CHECK_EQUAL( r.get_status_code(), websocketpp::http::status_code::ok );
1068  BOOST_CHECK_EQUAL( r.get_status_msg(), "OK" );
1069  BOOST_CHECK_EQUAL( r.get_header("Date"), "Thu, 10 May 2012 11:59:25 GMT" );
1070  BOOST_CHECK_EQUAL( r.get_header("Server"), "Apache/2.2.21 (Unix) mod_ssl/2.2.21 OpenSSL/0.9.8r DAV/2 PHP/5.3.8 with Suhosin-Patch" );
1071  BOOST_CHECK_EQUAL( r.get_header("Last-Modified"), "Tue, 30 Mar 2010 17:41:28 GMT" );
1072  BOOST_CHECK_EQUAL( r.get_header("ETag"), "\"16799d-55-4830823a78200\"" );
1073  BOOST_CHECK_EQUAL( r.get_header("Accept-Ranges"), "bytes" );
1074  BOOST_CHECK_EQUAL( r.get_header("Content-Length"), "85" );
1075  BOOST_CHECK_EQUAL( r.get_header("Vary"), "Accept-Encoding" );
1076  BOOST_CHECK_EQUAL( r.get_header("Content-Type"), "text/html" );
1077  BOOST_CHECK_EQUAL( r.get_body(), "<!doctype html>\n<html>\n<head>\n<title>Thor</title>\n</head>\n<body> \n<p>Thor</p>\n</body>" );
1078 }
1079 
1080 BOOST_AUTO_TEST_CASE( parse_istream ) {
1082 
1083  std::stringstream s;
1084 
1085  s << "HTTP/1.1 200 OK\r\nDate: Thu, 10 May 2012 11:59:25 GMT\r\nServer: Apache/2.2.21 (Unix) mod_ssl/2.2.21 OpenSSL/0.9.8r DAV/2 PHP/5.3.8 with Suhosin-Patch\r\nLast-Modified: Tue, 30 Mar 2010 17:41:28 GMT\r\nETag: \"16799d-55-4830823a78200\"\r\nAccept-Ranges: bytes\r\nContent-Length: 85\r\nVary: Accept-Encoding\r\nContent-Type: text/html\r\n\r\n<!doctype html>\n<html>\n<head>\n<title>Thor</title>\n</head>\n<body> \n<p>Thor</p>\n</body>";
1086 
1087  bool exception = false;
1088  size_t pos = 0;
1089 
1090  try {
1091  pos += r.consume(s);
1092  } catch (std::exception &e) {
1093  exception = true;
1094  std::cout << e.what() << std::endl;
1095  }
1096 
1097  BOOST_CHECK_EQUAL( exception, false );
1098  BOOST_CHECK_EQUAL( pos, 405 );
1099  BOOST_CHECK_EQUAL( r.headers_ready(), true );
1100  BOOST_CHECK_EQUAL( r.ready(), true );
1101 }
1102 
1103 BOOST_AUTO_TEST_CASE( write_request_basic ) {
1105 
1106  std::string raw = "GET / HTTP/1.1\r\n\r\n";
1107 
1108  r.set_version("HTTP/1.1");
1109  r.set_method("GET");
1110  r.set_uri("/");
1111 
1112  BOOST_CHECK_EQUAL( r.raw(), raw );
1113 }
1114 
1115 BOOST_AUTO_TEST_CASE( write_request_with_header ) {
1117 
1118  std::string raw = "GET / HTTP/1.1\r\nHost: http://example.com\r\n\r\n";
1119 
1120  r.set_version("HTTP/1.1");
1121  r.set_method("GET");
1122  r.set_uri("/");
1123  r.replace_header("Host","http://example.com");
1124 
1125  BOOST_CHECK_EQUAL( r.raw(), raw );
1126 }
1127 
1128 BOOST_AUTO_TEST_CASE( write_request_with_body ) {
1130 
1131  std::string raw = "POST / HTTP/1.1\r\nContent-Length: 48\r\nContent-Type: application/x-www-form-urlencoded\r\nHost: http://example.com\r\n\r\nlicenseID=string&content=string&paramsXML=string";
1132 
1133  r.set_version("HTTP/1.1");
1134  r.set_method("POST");
1135  r.set_uri("/");
1136  r.replace_header("Host","http://example.com");
1137  r.replace_header("Content-Type","application/x-www-form-urlencoded");
1138  r.set_body("licenseID=string&content=string&paramsXML=string");
1139 
1140  BOOST_CHECK_EQUAL( r.raw(), raw );
1141 }
std::string const & get_header(std::string const &key) const
Get the value of an HTTP header.
Definition: parser.hpp:45
BOOST_AUTO_TEST_CASE(is_token_char)
Definition: parser.cpp:37
bool ready() const
Returns true if the response is ready.
Definition: response.hpp:116
size_t get_max_body_size() const
Get body size limit.
Definition: parser.hpp:529
header_list const & get_headers() const
Return a list of all HTTP headers.
Definition: parser.hpp:179
status_code::value m_error_code
Definition: constants.hpp:303
void set_body(std::string const &value)
Set body content.
Definition: parser.hpp:91
std::vector< std::pair< std::string, attribute_list > > parameter_list
The type of an HTTP parameter list.
Definition: constants.hpp:53
bool is_not_token_char(unsigned char c)
Is the character a non-token.
Definition: constants.hpp:103
status_code::value get_status_code() const
Return the response status code.
Definition: response.hpp:152
Stores, parses, and manipulates HTTP responses.
Definition: response.hpp:57
std::string const & get_version() const
Get the HTTP version string.
Definition: parser.hpp:410
InputIterator extract_parameters(InputIterator begin, InputIterator end, parameter_list &parameters)
Extract HTTP parameters.
Definition: parser.hpp:293
InputIterator extract_attributes(InputIterator begin, InputIterator end, attribute_list &attributes)
Extract HTTP attributes.
Definition: parser.hpp:195
std::pair< std::string, InputIterator > extract_quoted_string(InputIterator begin, InputIterator end)
Read and return the next quoted string in the stream.
Definition: parser.hpp:92
std::string const & get_uri() const
Return the requested URI.
Definition: request.hpp:104
size_t const max_header_size
Maximum size in bytes before rejecting an HTTP header as too big.
Definition: constants.hpp:65
std::map< std::string, std::string > attribute_list
The type of an HTTP attribute list.
Definition: constants.hpp:45
std::string strip_lws(std::string const &input)
Definition: parser.hpp:379
void replace_header(std::string const &key, std::string const &val)
Set a value for an HTTP header, replacing an existing value.
Definition: parser.hpp:81
void set_uri(std::string const &uri)
Set the HTTP uri. Must be a valid HTTP uri.
Definition: request.hpp:159
void set_version(std::string const &version)
Set HTTP parser Version.
Definition: parser.hpp:41
std::string const & get_method() const
Return the request method.
Definition: request.hpp:96
Stores, parses, and manipulates HTTP requests.
Definition: request.hpp:50
size_t consume(char const *buf, size_t len)
Process bytes in the input buffer.
Definition: request.hpp:41
void set_method(std::string const &method)
Set the HTTP method. Must be a valid HTTP token.
Definition: request.hpp:151
size_t consume(char const *buf, size_t len)
Process bytes in the input buffer.
Definition: response.hpp:42
InputIterator extract_all_lws(InputIterator begin, InputIterator end)
Read and discard linear whitespace.
Definition: parser.hpp:164
std::string raw() const
Returns the full raw request (including the body)
Definition: request.hpp:131
bool ready() const
Returns whether or not the request is ready for reading.
Definition: request.hpp:82
std::pair< std::string, InputIterator > extract_token(InputIterator begin, InputIterator end)
Read and return the next token in the stream.
Definition: parser.hpp:73
bool headers_ready() const
Returns true if the response headers are fully parsed.
Definition: response.hpp:121
const std::string & get_status_msg() const
Return the response status message.
Definition: response.hpp:157
std::string const & get_body() const
Get HTTP body.
Definition: parser.hpp:505
void remove_header(std::string const &key)
Remove a header from the parser.
Definition: parser.hpp:87
bool is_token_char(unsigned char c)
Is the character a token.
Definition: constants.hpp:98
void set_max_body_size(size_t value)
Set body size limit.
Definition: parser.hpp:542