Skip to content

Commit 36eb5a7

Browse files
committed
Finishing Incremental Request Parser Implementation
This commit finishes the implementation of the incremental request parser. The next thing to do would be to integrate this into the HTTP connection handler.
1 parent 53d20b8 commit 36eb5a7

File tree

2 files changed

+90
-3
lines changed

2 files changed

+90
-3
lines changed

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

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,9 @@ namespace boost { namespace network { namespace http {
3636
, header_name
3737
, header_colon
3838
, header_value
39+
, header_cr
3940
, header_line_done
41+
, headers_cr
4042
, headers_done
4143
};
4244

@@ -125,6 +127,40 @@ namespace boost { namespace network { namespace http {
125127
if (*current_iterator == '\n') internal_state = version_done;
126128
else parsed_ok = false;
127129
break;
130+
case version_done:
131+
if (algorithm::is_alnum()(*current_iterator)) internal_state = header_name;
132+
else if (*current_iterator == '\r') internal_state = headers_cr;
133+
else parsed_ok = false;
134+
break;
135+
case header_name:
136+
if (*current_iterator == ':') internal_state = header_colon;
137+
else if (algorithm::is_alnum()(*current_iterator) || algorithm::is_punct()(*current_iterator)) break;
138+
else parsed_ok = false;
139+
break;
140+
case header_colon:
141+
if (*current_iterator == ' ') internal_state = header_value;
142+
else parsed_ok = false;
143+
break;
144+
case header_value:
145+
if (*current_iterator == '\r') internal_state = header_cr;
146+
else if (algorithm::is_cntrl()(*current_iterator)) parsed_ok = false;
147+
break;
148+
case header_cr:
149+
if (*current_iterator == '\n') internal_state = header_line_done;
150+
else parsed_ok = false;
151+
break;
152+
case header_line_done:
153+
if (*current_iterator == '\r') internal_state = headers_cr;
154+
else if (algorithm::is_alnum()(*current_iterator)) internal_state = header_name;
155+
else parsed_ok = false;
156+
break;
157+
case headers_cr:
158+
if (*current_iterator == '\n') internal_state = headers_done;
159+
else parsed_ok = false;
160+
break;
161+
case headers_done:
162+
// anything that follows after headers_done is allowed.
163+
break;
128164
default:
129165
parsed_ok = false;
130166
};

libs/network/test/http_incremental_request_parser.cpp

Lines changed: 54 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,16 @@ BOOST_AUTO_TEST_CASE(incremental_parser_parse_http_method) {
4747
BOOST_CHECK_EQUAL(parsed_ok, true);
4848
BOOST_CHECK(!boost::empty(result_range));
4949
std::string parsed(boost::begin(result_range), boost::end(result_range));
50-
std::cout << "PARSED: " << parsed << " " << p.state() << std::endl;
50+
std::cout << "PARSED: " << parsed << " [state:" << p.state() << "] " << std::endl;
51+
52+
std::string invalid_http_method = "get ";
53+
p.reset();
54+
fusion::tie(parsed_ok, result_range) = p.parse_until(
55+
request_parser_type::method_done
56+
, invalid_http_method);
57+
BOOST_CHECK_EQUAL(parsed_ok, false);
58+
parsed.assign(boost::begin(result_range), boost::end(result_range));
59+
std::cout << "PARSED: " << parsed << " [state:" << p.state() << "] " << std::endl;
5160
}
5261

5362
BOOST_AUTO_TEST_CASE(incremental_parser_parse_http_uri) {
@@ -63,7 +72,15 @@ BOOST_AUTO_TEST_CASE(incremental_parser_parse_http_uri) {
6372
BOOST_CHECK_EQUAL(parsed_ok, true);
6473
BOOST_CHECK(!boost::empty(result_range));
6574
std::string parsed(boost::begin(result_range), boost::end(result_range));
66-
std::cout << "PARSED: " << parsed << " " << p.state() << std::endl;
75+
std::cout << "PARSED: " << parsed << " [state:" << p.state() << "] " << std::endl;
76+
77+
std::string invalid_http_request = "GET /\t HTTP/1.1\r\n";
78+
p.reset();
79+
fusion::tie(parsed_ok, result_range) = p.parse_until(
80+
request_parser_type::uri_done, invalid_http_request);
81+
BOOST_CHECK_EQUAL(parsed_ok, false);
82+
parsed.assign(boost::begin(result_range), boost::end(result_range));
83+
std::cout << "PARSED: " << parsed << " [state:" << p.state() << "] " << std::endl;
6784
}
6885

6986
BOOST_AUTO_TEST_CASE(incremental_parser_parse_http_version) {
@@ -79,5 +96,39 @@ BOOST_AUTO_TEST_CASE(incremental_parser_parse_http_version) {
7996
BOOST_CHECK_EQUAL(parsed_ok, true);
8097
BOOST_CHECK(!boost::empty(result_range));
8198
std::string parsed(boost::begin(result_range), boost::end(result_range));
82-
std::cout << "PARSED: " << parsed << " " << p.state() << std::endl;
99+
std::cout << "PARSED: " << parsed << " [state:" << p.state() << "] " << std::endl;
100+
101+
std::string invalid_http_request = "GET / HTTP 1.1\r\n";
102+
p.reset();
103+
fusion::tie(parsed_ok, result_range) = p.parse_until(
104+
request_parser_type::version_done, invalid_http_request);
105+
BOOST_CHECK_EQUAL(parsed_ok, false);
106+
parsed.assign(boost::begin(result_range), boost::end(result_range));
107+
std::cout << "PARSED: " << parsed << " [state:" << p.state() << "] " << std::endl;
108+
}
109+
110+
BOOST_AUTO_TEST_CASE(incremental_parser_parse_http_headers) {
111+
request_parser<tags::default_string> p;
112+
logic::tribool parsed_ok = false;
113+
typedef request_parser<tags::default_string> request_parser_type;
114+
typedef boost::iterator_range<std::string::const_iterator> range_type;
115+
range_type result_range;
116+
117+
std::string valid_http_request = "GET / HTTP/1.1\r\nHost: cpp-netlib.org\r\n\r\n";
118+
fusion::tie(parsed_ok, result_range) = p.parse_until(
119+
request_parser_type::headers_done, valid_http_request);
120+
BOOST_CHECK_EQUAL(parsed_ok, true);
121+
BOOST_CHECK(!boost::empty(result_range));
122+
std::string parsed(boost::begin(result_range), boost::end(result_range));
123+
std::cout << "PARSED: " << parsed << " [state:" << p.state() << "] " << std::endl;
124+
125+
valid_http_request = "GET / HTTP/1.1\r\nHost: cpp-netlib.org\r\nConnection: close\r\n\r\n";
126+
p.reset();
127+
fusion::tie(parsed_ok, result_range) = p.parse_until(
128+
request_parser_type::headers_done, valid_http_request);
129+
BOOST_CHECK_EQUAL(parsed_ok, true);
130+
BOOST_CHECK(!boost::empty(result_range));
131+
parsed.assign(boost::begin(result_range), boost::end(result_range));
132+
std::cout << "PARSED: " << parsed << " [state:" << p.state() << "] " << std::endl;
83133
}
134+

0 commit comments

Comments
 (0)