10 #include <boost/bind.hpp>
17 const int HttpResponseParser::RECEIVE_START_ST;
18 const int HttpResponseParser::HTTP_VERSION_H_ST;
19 const int HttpResponseParser::HTTP_VERSION_T1_ST;
20 const int HttpResponseParser::HTTP_VERSION_T2_ST;
21 const int HttpResponseParser::HTTP_VERSION_P_ST;
22 const int HttpResponseParser::HTTP_VERSION_SLASH_ST;
23 const int HttpResponseParser::HTTP_VERSION_MAJOR_START_ST;
24 const int HttpResponseParser::HTTP_VERSION_MAJOR_ST;
25 const int HttpResponseParser::HTTP_VERSION_MINOR_START_ST;
26 const int HttpResponseParser::HTTP_VERSION_MINOR_ST;
27 const int HttpResponseParser::HTTP_STATUS_CODE_START_ST;
28 const int HttpResponseParser::HTTP_STATUS_CODE_ST;
29 const int HttpResponseParser::HTTP_PHRASE_START_ST;
30 const int HttpResponseParser::HTTP_PHRASE_ST;
31 const int HttpResponseParser::EXPECTING_NEW_LINE1_ST;
32 const int HttpResponseParser::HEADER_LINE_START_ST;
33 const int HttpResponseParser::HEADER_LWS_ST;
34 const int HttpResponseParser::HEADER_NAME_ST;
35 const int HttpResponseParser::SPACE_BEFORE_HEADER_VALUE_ST;
36 const int HttpResponseParser::HEADER_VALUE_ST;
37 const int HttpResponseParser::EXPECTING_NEW_LINE2_ST;
38 const int HttpResponseParser::EXPECTING_NEW_LINE3_ST;
39 const int HttpResponseParser::HTTP_BODY_ST;
43 context_(response.context()) {
59 HttpResponseParser::defineStates() {
65 boost::bind(&HttpResponseParser::receiveStartHandler,
this));
68 boost::bind(&HttpResponseParser::versionHTTPHandler,
this,
'T',
72 boost::bind(&HttpResponseParser::versionHTTPHandler,
this,
'T',
76 boost::bind(&HttpResponseParser::versionHTTPHandler,
this,
'P',
80 boost::bind(&HttpResponseParser::versionHTTPHandler,
this,
'/',
84 boost::bind(&HttpResponseParser::numberStartHandler,
this,
87 &context_->http_version_major_));
90 boost::bind(&HttpResponseParser::numberHandler,
this,
93 &context_->http_version_major_));
96 boost::bind(&HttpResponseParser::numberStartHandler,
this,
99 &context_->http_version_minor_));
102 boost::bind(&HttpResponseParser::numberHandler,
this,
105 &context_->http_version_minor_));
108 boost::bind(&HttpResponseParser::numberStartHandler,
this,
111 &context_->status_code_));
114 boost::bind(&HttpResponseParser::numberHandler,
this,
117 &context_->status_code_));
120 boost::bind(&HttpResponseParser::phraseStartHandler,
this));
123 boost::bind(&HttpResponseParser::phraseHandler,
this));
126 boost::bind(&HttpResponseParser::expectingNewLineHandler,
this,
130 boost::bind(&HttpResponseParser::headerLineStartHandler,
this));
133 boost::bind(&HttpResponseParser::headerLwsHandler,
this));
136 boost::bind(&HttpResponseParser::headerNameHandler,
this));
139 boost::bind(&HttpResponseParser::spaceBeforeHeaderValueHandler,
this));
142 boost::bind(&HttpResponseParser::headerValueHandler,
this));
145 boost::bind(&HttpResponseParser::expectingNewLineHandler,
this,
149 boost::bind(&HttpResponseParser::expectingNewLineHandler,
this,
153 boost::bind(&HttpResponseParser::bodyHandler,
this));
157 HttpResponseParser::receiveStartHandler() {
163 if (bytes[0] ==
'H') {
167 parseFailure(
"unexpected first character " + std::string(1, bytes[0]) +
179 HttpResponseParser::versionHTTPHandler(
const char expected_letter,
180 const unsigned int next_state) {
182 [
this, expected_letter, next_state](
const char c) {
184 if (c == expected_letter) {
189 context_->http_version_major_ = 0;
190 context_->http_version_minor_ = 0;
197 parseFailure(
"unexpected character " + std::string(1, c) +
198 " in HTTP version string");
204 HttpResponseParser::numberStartHandler(
const unsigned int next_state,
205 const std::string& number_name,
206 unsigned int* storage) {
208 [
this, next_state, number_name, storage](
const char c)
mutable {
212 *storage = *storage * 10 + c -
'0';
216 parseFailure(
"expected digit in " + number_name +
", found " +
223 HttpResponseParser::numberHandler(
const char following_character,
224 const unsigned int next_state,
225 const std::string& number_name,
226 unsigned int*
const storage) {
228 [
this, following_character, number_name, next_state, storage](
const char c)
232 if (c == following_character) {
235 }
else if (isdigit(c)) {
237 *storage = *storage * 10 + c -
'0';
240 parseFailure(
"expected digit in " + number_name +
", found " +
247 HttpResponseParser::phraseStartHandler() {
250 parseFailure(
"invalid first character " + std::string(1, c) +
253 context_->phrase_.push_back(c);
260 HttpResponseParser::phraseHandler() {
270 context_->phrase_.push_back(c);
277 HttpResponseParser::expectingNewLineHandler(
const unsigned int next_state) {
293 uint64_t content_length =
295 if (content_length > 0) {
299 }
catch (
const std::exception& ex) {
324 HttpResponseParser::headerLineStartHandler() {
331 }
else if (!context_->headers_.empty() && ((c ==
' ') || (c ==
'\t'))) {
342 context_->headers_.push_back(HttpHeaderContext());
343 context_->headers_.back().name_.push_back(c);
350 HttpResponseParser::headerLwsHandler() {
357 }
else if ((c ==
' ') || (c ==
'\t')) {
362 }
else if (
isCtl(c)) {
363 parseFailure(
"control character found in the HTTP header " +
364 context_->headers_.back().name_);
368 context_->headers_.back().value_.push_back(c);
375 HttpResponseParser::headerNameHandler() {
383 " found in the HTTP header name");
387 context_->headers_.back().name_.push_back(c);
394 HttpResponseParser::spaceBeforeHeaderValueHandler() {
400 }
else if (c ==
'\r') {
405 }
else if (
isCtl(c)) {
406 parseFailure(
"control character found in the HTTP header "
407 + context_->headers_.back().name_);
411 context_->headers_.back().value_.push_back(c);
418 HttpResponseParser::headerValueHandler() {
425 }
else if (
isCtl(c)) {
426 parseFailure(
"control character found in the HTTP header "
427 + context_->headers_.back().name_);
431 context_->headers_.back().value_.push_back(c);
438 HttpResponseParser::bodyHandler() {
442 context_->body_ += body;
444 if (context_->body_.length() < content_length) {
445 transition(HTTP_BODY_ST, DATA_READ_OK_EVT);
449 if (context_->body_.length() > content_length) {
450 context_->body_.resize(content_length);