Skip to content

Commit 53d20b8

Browse files
committed
Fleshing out Incremental Parser Implementation
Now the parser can actually parse up to the HTTP version of the request range.
1 parent adac71b commit 53d20b8

File tree

2 files changed

+100
-3
lines changed

2 files changed

+100
-3
lines changed

boost/network/protocol/http/server/request_parser.hpp

Lines changed: 65 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include <boost/range/iterator_range.hpp>
1111
#include <boost/logic/tribool.hpp>
1212
#include <boost/fusion/tuple.hpp>
13+
#include <boost/algorithm/string/classification.hpp>
1314

1415
namespace boost { namespace network { namespace http {
1516

@@ -26,9 +27,11 @@ namespace boost { namespace network { namespace http {
2627
, version_t1
2728
, version_t2
2829
, version_p
30+
, version_slash
2931
, version_d1
3032
, version_dot
3133
, version_d2
34+
, version_cr
3235
, version_done
3336
, header_name
3437
, header_colon
@@ -50,7 +53,7 @@ namespace boost { namespace network { namespace http {
5053
template <class Range>
5154
fusion::tuple<logic::tribool, iterator_range<typename Range::const_iterator> >
5255
parse_until(state_t stop_state, Range & range) {
53-
logic::tribool parsed_ok;
56+
logic::tribool parsed_ok = logic::indeterminate;
5457
typedef typename range_iterator<Range>::type iterator;
5558
iterator start = boost::begin(range)
5659
, end = boost::end(range)
@@ -60,12 +63,72 @@ namespace boost { namespace network { namespace http {
6063
while (
6164
!boost::empty(local_range)
6265
&& stop_state != internal_state
63-
&& parsed_ok == logic::indeterminate
66+
&& indeterminate(parsed_ok)
6467
) {
68+
current_iterator = boost::begin(local_range);
6569
switch(internal_state) {
70+
case method_start:
71+
if (algorithm::is_upper()(*current_iterator)) internal_state = method_char;
72+
else parsed_ok = false;
73+
break;
74+
case method_char:
75+
if (algorithm::is_upper()(*current_iterator)) break;
76+
else if (algorithm::is_space()(*current_iterator)) internal_state = method_done;
77+
else parsed_ok = false;
78+
break;
79+
case method_done:
80+
if (algorithm::is_cntrl()(*current_iterator)) parsed_ok = false;
81+
else if (algorithm::is_space()(*current_iterator)) parsed_ok = false;
82+
else internal_state = uri_char;
83+
break;
84+
case uri_char:
85+
if (algorithm::is_cntrl()(*current_iterator)) parsed_ok = false;
86+
else if (algorithm::is_space()(*current_iterator)) internal_state = uri_done;
87+
break;
88+
case uri_done:
89+
if (*current_iterator == 'H') internal_state = version_h;
90+
else parsed_ok = false;
91+
break;
92+
case version_h:
93+
if (*current_iterator == 'T') internal_state = version_t1;
94+
else parsed_ok = false;
95+
break;
96+
case version_t1:
97+
if (*current_iterator == 'T') internal_state = version_t2;
98+
else parsed_ok = false;
99+
break;
100+
case version_t2:
101+
if (*current_iterator == 'P') internal_state = version_p;
102+
else parsed_ok = false;
103+
break;
104+
case version_p:
105+
if (*current_iterator == '/') internal_state = version_slash;
106+
else parsed_ok = false;
107+
break;
108+
case version_slash:
109+
if (algorithm::is_digit()(*current_iterator)) internal_state = version_d1;
110+
else parsed_ok = false;
111+
break;
112+
case version_d1:
113+
if (*current_iterator == '.') internal_state = version_dot;
114+
else parsed_ok = false;
115+
break;
116+
case version_dot:
117+
if (algorithm::is_digit()(*current_iterator)) internal_state = version_d2;
118+
else parsed_ok = false;
119+
break;
120+
case version_d2:
121+
if (*current_iterator == '\r') internal_state = version_cr;
122+
else parsed_ok = false;
123+
break;
124+
case version_cr:
125+
if (*current_iterator == '\n') internal_state = version_done;
126+
else parsed_ok = false;
127+
break;
66128
default:
67129
parsed_ok = false;
68130
};
131+
if (internal_state == stop_state) parsed_ok = true;
69132
local_range = boost::make_iterator_range(
70133
++current_iterator, end);
71134
}

libs/network/test/http_incremental_request_parser.cpp

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,10 +40,44 @@ BOOST_AUTO_TEST_CASE(incremental_parser_parse_http_method) {
4040
typedef boost::iterator_range<std::string::const_iterator> range_type;
4141
range_type result_range;
4242

43-
std::string valid_http_method = "GET";
43+
std::string valid_http_method = "GET ";
4444
fusion::tie(parsed_ok, result_range) = p.parse_until(
4545
request_parser_type::method_done
4646
, valid_http_method);
4747
BOOST_CHECK_EQUAL(parsed_ok, true);
4848
BOOST_CHECK(!boost::empty(result_range));
49+
std::string parsed(boost::begin(result_range), boost::end(result_range));
50+
std::cout << "PARSED: " << parsed << " " << p.state() << std::endl;
51+
}
52+
53+
BOOST_AUTO_TEST_CASE(incremental_parser_parse_http_uri) {
54+
request_parser<tags::default_string> p;
55+
logic::tribool parsed_ok = false;
56+
typedef request_parser<tags::default_string> request_parser_type;
57+
typedef boost::iterator_range<std::string::const_iterator> range_type;
58+
range_type result_range;
59+
60+
std::string valid_http_request = "GET / HTTP/1.1\r\n";
61+
fusion::tie(parsed_ok, result_range) = p.parse_until(
62+
request_parser_type::uri_done, valid_http_request);
63+
BOOST_CHECK_EQUAL(parsed_ok, true);
64+
BOOST_CHECK(!boost::empty(result_range));
65+
std::string parsed(boost::begin(result_range), boost::end(result_range));
66+
std::cout << "PARSED: " << parsed << " " << p.state() << std::endl;
67+
}
68+
69+
BOOST_AUTO_TEST_CASE(incremental_parser_parse_http_version) {
70+
request_parser<tags::default_string> p;
71+
logic::tribool parsed_ok = false;
72+
typedef request_parser<tags::default_string> request_parser_type;
73+
typedef boost::iterator_range<std::string::const_iterator> range_type;
74+
range_type result_range;
75+
76+
std::string valid_http_request = "GET / HTTP/1.1\r\n";
77+
fusion::tie(parsed_ok, result_range) = p.parse_until(
78+
request_parser_type::version_done, valid_http_request);
79+
BOOST_CHECK_EQUAL(parsed_ok, true);
80+
BOOST_CHECK(!boost::empty(result_range));
81+
std::string parsed(boost::begin(result_range), boost::end(result_range));
82+
std::cout << "PARSED: " << parsed << " " << p.state() << std::endl;
4983
}

0 commit comments

Comments
 (0)