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 
34 #include <websocketpp/http/request.hpp>
35 #include <websocketpp/http/response.hpp>
36 
BOOST_AUTO_TEST_CASE(is_token_char)37 BOOST_AUTO_TEST_CASE( is_token_char ) {
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 
BOOST_AUTO_TEST_CASE(extract_token)107 BOOST_AUTO_TEST_CASE( extract_token ) {
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 
BOOST_AUTO_TEST_CASE(extract_quoted_string)126 BOOST_AUTO_TEST_CASE( extract_quoted_string ) {
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 
135     using websocketpp::http::parser::extract_quoted_string;
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 
BOOST_AUTO_TEST_CASE(extract_all_lws)158 BOOST_AUTO_TEST_CASE( extract_all_lws ) {
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 
BOOST_AUTO_TEST_CASE(extract_attributes_blank)187 BOOST_AUTO_TEST_CASE( extract_attributes_blank ) {
188     std::string s;
189 
190     websocketpp::http::attribute_list a;
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 
BOOST_AUTO_TEST_CASE(extract_attributes_simple)198 BOOST_AUTO_TEST_CASE( extract_attributes_simple ) {
199     std::string s = "foo";
200 
201     websocketpp::http::attribute_list a;
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 
BOOST_AUTO_TEST_CASE(extract_parameters)211 BOOST_AUTO_TEST_CASE( extract_parameters ) {
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\"";
228     websocketpp::http::parameter_list p;
229     websocketpp::http::attribute_list a;
230     std::string::const_iterator it;
231 
232     using websocketpp::http::parser::extract_parameters;
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 
BOOST_AUTO_TEST_CASE(strip_lws)359 BOOST_AUTO_TEST_CASE( strip_lws ) {
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 
BOOST_AUTO_TEST_CASE(case_insensitive_headers)381 BOOST_AUTO_TEST_CASE( case_insensitive_headers ) {
382     websocketpp::http::parser::parser r;
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 
BOOST_AUTO_TEST_CASE(case_insensitive_headers_overwrite)391 BOOST_AUTO_TEST_CASE( case_insensitive_headers_overwrite ) {
392     websocketpp::http::parser::parser r;
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 
BOOST_AUTO_TEST_CASE(blank_consume)410 BOOST_AUTO_TEST_CASE( blank_consume ) {
411     websocketpp::http::parser::request r;
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 
BOOST_AUTO_TEST_CASE(blank_request)427 BOOST_AUTO_TEST_CASE( blank_request ) {
428     websocketpp::http::parser::request r;
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 
BOOST_AUTO_TEST_CASE(bad_request_no_host)444 BOOST_AUTO_TEST_CASE( bad_request_no_host ) {
445     websocketpp::http::parser::request r;
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 
BOOST_AUTO_TEST_CASE(basic_request)461 BOOST_AUTO_TEST_CASE( basic_request ) {
462     websocketpp::http::parser::request r;
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 
BOOST_AUTO_TEST_CASE(basic_request_with_body)485 BOOST_AUTO_TEST_CASE( basic_request_with_body ) {
486     websocketpp::http::parser::request r;
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 
BOOST_AUTO_TEST_CASE(basic_request_with_body_split)523 BOOST_AUTO_TEST_CASE( basic_request_with_body_split ) {
524     websocketpp::http::parser::request r;
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 
BOOST_AUTO_TEST_CASE(trailing_body_characters)553 BOOST_AUTO_TEST_CASE( trailing_body_characters ) {
554     websocketpp::http::parser::request r;
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 
BOOST_AUTO_TEST_CASE(trailing_body_characters_beyond_max_lenth)576 BOOST_AUTO_TEST_CASE( trailing_body_characters_beyond_max_lenth ) {
577     websocketpp::http::parser::request r;
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 
BOOST_AUTO_TEST_CASE(basic_split1)600 BOOST_AUTO_TEST_CASE( basic_split1 ) {
601     websocketpp::http::parser::request r;
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 
BOOST_AUTO_TEST_CASE(basic_split2)626 BOOST_AUTO_TEST_CASE( basic_split2 ) {
627     websocketpp::http::parser::request r;
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 
BOOST_AUTO_TEST_CASE(max_header_len)652 BOOST_AUTO_TEST_CASE( max_header_len ) {
653     websocketpp::http::parser::request r;
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) {
664         if (e.m_error_code == websocketpp::http::status_code::request_header_fields_too_large) {
665             exception = true;
666         }
667     }
668 
669     BOOST_CHECK( exception == true );
670 }
671 
BOOST_AUTO_TEST_CASE(max_header_len_split)672 BOOST_AUTO_TEST_CASE( max_header_len_split ) {
673     websocketpp::http::parser::request r;
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) {
685         if (e.m_error_code == websocketpp::http::status_code::request_header_fields_too_large) {
686             exception = true;
687         }
688     }
689 
690     BOOST_CHECK( exception == true );
691 }
692 
BOOST_AUTO_TEST_CASE(max_body_len)693 BOOST_AUTO_TEST_CASE( max_body_len ) {
694     websocketpp::http::parser::request r;
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;
707         BOOST_CHECK_EQUAL(e.m_error_code,websocketpp::http::status_code::request_entity_too_large);
708     }
709 
710     BOOST_CHECK_EQUAL(r.get_max_body_size(),5);
711     BOOST_CHECK( exception == true );
712 }
713 
BOOST_AUTO_TEST_CASE(firefox_full_request)714 BOOST_AUTO_TEST_CASE( firefox_full_request ) {
715     websocketpp::http::parser::request r;
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 
BOOST_AUTO_TEST_CASE(bad_method)748 BOOST_AUTO_TEST_CASE( bad_method ) {
749     websocketpp::http::parser::request r;
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 
BOOST_AUTO_TEST_CASE(bad_header_name)764 BOOST_AUTO_TEST_CASE( bad_header_name ) {
765     websocketpp::http::parser::request r;
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 
BOOST_AUTO_TEST_CASE(old_http_version)780 BOOST_AUTO_TEST_CASE( old_http_version ) {
781     websocketpp::http::parser::request r;
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 
BOOST_AUTO_TEST_CASE(new_http_version1)803 BOOST_AUTO_TEST_CASE( new_http_version1 ) {
804     websocketpp::http::parser::request r;
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 
BOOST_AUTO_TEST_CASE(new_http_version2)826 BOOST_AUTO_TEST_CASE( new_http_version2 ) {
827     websocketpp::http::parser::request r;
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 
BOOST_AUTO_TEST_CASE(header_whitespace1)868 BOOST_AUTO_TEST_CASE( header_whitespace1 ) {
869     websocketpp::http::parser::request r;
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 
BOOST_AUTO_TEST_CASE(header_whitespace2)891 BOOST_AUTO_TEST_CASE( header_whitespace2 ) {
892     websocketpp::http::parser::request r;
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 
BOOST_AUTO_TEST_CASE(header_aggregation)914 BOOST_AUTO_TEST_CASE( header_aggregation ) {
915     websocketpp::http::parser::request r;
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 
BOOST_AUTO_TEST_CASE(wikipedia_example_response)937 BOOST_AUTO_TEST_CASE( wikipedia_example_response ) {
938     websocketpp::http::parser::response r;
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" );
956     BOOST_CHECK_EQUAL( r.get_status_code(), websocketpp::http::status_code::switching_protocols );
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 
BOOST_AUTO_TEST_CASE(wikipedia_example_response_trailing)964 BOOST_AUTO_TEST_CASE( wikipedia_example_response_trailing ) {
965     websocketpp::http::parser::response r;
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" );
984     BOOST_CHECK_EQUAL( r.get_status_code(), websocketpp::http::status_code::switching_protocols );
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 
BOOST_AUTO_TEST_CASE(wikipedia_example_response_trailing_large)992 BOOST_AUTO_TEST_CASE( wikipedia_example_response_trailing_large ) {
993     websocketpp::http::parser::response r;
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" );
1012     BOOST_CHECK_EQUAL( r.get_status_code(), websocketpp::http::status_code::switching_protocols );
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 
BOOST_AUTO_TEST_CASE(response_with_non_standard_lws)1020 BOOST_AUTO_TEST_CASE( response_with_non_standard_lws ) {
1021     websocketpp::http::parser::response r;
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" );
1039     BOOST_CHECK_EQUAL( r.get_status_code(), websocketpp::http::status_code::switching_protocols );
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 
BOOST_AUTO_TEST_CASE(plain_http_response)1047 BOOST_AUTO_TEST_CASE( plain_http_response ) {
1048     websocketpp::http::parser::response r;
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 
BOOST_AUTO_TEST_CASE(parse_istream)1080 BOOST_AUTO_TEST_CASE( parse_istream ) {
1081     websocketpp::http::parser::response r;
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 
BOOST_AUTO_TEST_CASE(write_request_basic)1103 BOOST_AUTO_TEST_CASE( write_request_basic ) {
1104     websocketpp::http::parser::request r;
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 
BOOST_AUTO_TEST_CASE(write_request_with_header)1115 BOOST_AUTO_TEST_CASE( write_request_with_header ) {
1116     websocketpp::http::parser::request r;
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 
BOOST_AUTO_TEST_CASE(write_request_with_body)1128 BOOST_AUTO_TEST_CASE( write_request_with_body ) {
1129     websocketpp::http::parser::request r;
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 }
1142