Skip to content

Commit 09c705b

Browse files
author
Dean Michael Berris
committed
Implementing header line parsing.
1 parent 92c315f commit 09c705b

File tree

2 files changed

+95
-1
lines changed

2 files changed

+95
-1
lines changed

boost/network/protocol/http/parser/incremental.hpp

Lines changed: 66 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,14 @@ namespace boost { namespace network { namespace http {
3434
http_status_done,
3535
http_status_message_char,
3636
http_status_message_cr,
37-
http_status_message_done
37+
http_status_message_done,
38+
http_header_name_char,
39+
http_header_colon,
40+
http_header_value_char,
41+
http_header_line_cr,
42+
http_header_line_done,
43+
http_headers_end_cr,
44+
http_headers_done
3845
};
3946

4047
typedef typename string<Tag>::type::const_iterator iterator_type;
@@ -197,6 +204,64 @@ namespace boost { namespace network { namespace http {
197204
parsed_ok = false;
198205
}
199206
break;
207+
case http_status_message_done:
208+
case http_header_line_done:
209+
if (algorithm::is_alnum()(*current)) {
210+
state_ = http_header_name_char;
211+
++current;
212+
} else if (*current == '\r') {
213+
state_ = http_headers_end_cr;
214+
++current;
215+
} else {
216+
parsed_ok = false;
217+
}
218+
break;
219+
case http_header_name_char:
220+
if (*current == ':') {
221+
state_ = http_header_colon;
222+
++current;
223+
} else if (algorithm::is_alnum()(*current) || algorithm::is_space()(*current) || algorithm::is_punct()(*current)) {
224+
++current;
225+
} else {
226+
parsed_ok = false;
227+
}
228+
break;
229+
case http_header_colon:
230+
if (algorithm::is_space()(*current)) {
231+
++current;
232+
} else if (algorithm::is_alnum()(*current) || algorithm::is_punct()(*current)) {
233+
state_ = http_header_value_char;
234+
++current;
235+
} else {
236+
parsed_ok = false;
237+
}
238+
break;
239+
case http_header_value_char:
240+
if (*current == '\r') {
241+
state_ = http_header_line_cr;
242+
++current;
243+
} else if (algorithm::is_cntrl()(*current)) {
244+
parsed_ok = false;
245+
} else {
246+
++current;
247+
}
248+
break;
249+
case http_header_line_cr:
250+
if (*current == '\n') {
251+
state_ = http_header_line_done;
252+
++current;
253+
} else {
254+
parsed_ok = false;
255+
}
256+
break;
257+
case http_headers_end_cr:
258+
if (*current == '\n') {
259+
state_ = http_headers_done;
260+
++current;
261+
} else {
262+
parsed_ok = false;
263+
}
264+
break;
200265
default:
201266
parsed_ok = false;
202267
}

libs/network/test/http_incremental_parser.cpp

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,3 +169,32 @@ BOOST_AUTO_TEST_CASE(incremental_parser_parse_status_message) {
169169
std::cout << "PARSED: " << parsed << " state=" << p.state() << std::endl;
170170
}
171171

172+
BOOST_AUTO_TEST_CASE(incremental_parser_parse_header_lines) {
173+
typedef response_parser<tags::default_string> response_parser_type;
174+
typedef response_parser_type::range_type range_type;
175+
response_parser_type p(response_parser_type::http_status_message_done);
176+
177+
std::string valid_headers = "Server: Foo\r\nContent-Type: application/json\r\n\r\n";
178+
logic::tribool parsed_ok;
179+
range_type result_range;
180+
fusion::tie(parsed_ok, result_range) = p.parse_until(
181+
response_parser_type::http_header_line_done,
182+
valid_headers);
183+
BOOST_CHECK_EQUAL(parsed_ok, true);
184+
std::string parsed1 = std::string(boost::begin(result_range), boost::end(result_range));
185+
p.reset(response_parser_type::http_status_message_done);
186+
std::string::const_iterator end = valid_headers.end();
187+
valid_headers.assign(boost::end(result_range), end);
188+
fusion::tie(parsed_ok, result_range) = p.parse_until(
189+
response_parser_type::http_header_line_done,
190+
valid_headers);
191+
BOOST_CHECK_EQUAL(parsed_ok, true);
192+
std::string parsed2 = std::string(boost::begin(result_range), boost::end(result_range));
193+
valid_headers.assign(boost::end(result_range), end);
194+
p.reset(response_parser_type::http_status_message_done);
195+
fusion::tie(parsed_ok, result_range) = p.parse_until(
196+
response_parser_type::http_headers_done,
197+
valid_headers);
198+
BOOST_CHECK_EQUAL(parsed_ok, true);
199+
BOOST_CHECK(parsed1 != parsed2);
200+
}

0 commit comments

Comments
 (0)