10 #include <boost/bind.hpp>
18 const int HttpRequestParser::RECEIVE_START_ST;
19 const int HttpRequestParser::HTTP_METHOD_ST;
20 const int HttpRequestParser::HTTP_URI_ST;
21 const int HttpRequestParser::HTTP_VERSION_H_ST;
22 const int HttpRequestParser::HTTP_VERSION_T1_ST;
23 const int HttpRequestParser::HTTP_VERSION_T2_ST;
24 const int HttpRequestParser::HTTP_VERSION_P_ST;
25 const int HttpRequestParser::HTTP_VERSION_SLASH_ST;
26 const int HttpRequestParser::HTTP_VERSION_MAJOR_START_ST;
27 const int HttpRequestParser::HTTP_VERSION_MAJOR_ST;
28 const int HttpRequestParser::HTTP_VERSION_MINOR_START_ST;
29 const int HttpRequestParser::HTTP_VERSION_MINOR_ST;
30 const int HttpRequestParser::EXPECTING_NEW_LINE1_ST;
31 const int HttpRequestParser::HEADER_LINE_START_ST;
32 const int HttpRequestParser::HEADER_LWS_ST;
33 const int HttpRequestParser::HEADER_NAME_ST;
34 const int HttpRequestParser::SPACE_BEFORE_HEADER_VALUE_ST;
35 const int HttpRequestParser::HEADER_VALUE_ST;
36 const int HttpRequestParser::EXPECTING_NEW_LINE2_ST;
37 const int HttpRequestParser::EXPECTING_NEW_LINE3_ST;
38 const int HttpRequestParser::HTTP_BODY_ST;
42 context_(request_.context()) {
58 HttpRequestParser::defineStates() {
64 boost::bind(&HttpRequestParser::receiveStartHandler,
this));
67 boost::bind(&HttpRequestParser::httpMethodHandler,
this));
70 boost::bind(&HttpRequestParser::uriHandler,
this));
73 boost::bind(&HttpRequestParser::versionHTTPHandler,
this,
'H',
77 boost::bind(&HttpRequestParser::versionHTTPHandler,
this,
'T',
81 boost::bind(&HttpRequestParser::versionHTTPHandler,
this,
'T',
85 boost::bind(&HttpRequestParser::versionHTTPHandler,
this,
'P',
89 boost::bind(&HttpRequestParser::versionHTTPHandler,
this,
'/',
93 boost::bind(&HttpRequestParser::versionNumberStartHandler,
this,
95 &context_->http_version_major_));
98 boost::bind(&HttpRequestParser::versionNumberHandler,
this,
100 &context_->http_version_major_));
103 boost::bind(&HttpRequestParser::versionNumberStartHandler,
this,
105 &context_->http_version_minor_));
108 boost::bind(&HttpRequestParser::versionNumberHandler,
this,
110 &context_->http_version_minor_));
113 boost::bind(&HttpRequestParser::expectingNewLineHandler,
this,
117 boost::bind(&HttpRequestParser::headerLineStartHandler,
this));
120 boost::bind(&HttpRequestParser::headerLwsHandler,
this));
123 boost::bind(&HttpRequestParser::headerNameHandler,
this));
126 boost::bind(&HttpRequestParser::spaceBeforeHeaderValueHandler,
this));
129 boost::bind(&HttpRequestParser::headerValueHandler,
this));
132 boost::bind(&HttpRequestParser::expectingNewLineHandler,
this,
136 boost::bind(&HttpRequestParser::expectingNewLineHandler,
this,
140 boost::bind(&HttpRequestParser::bodyHandler,
this));
144 HttpRequestParser::receiveStartHandler() {
153 parseFailure(
"invalid first character " + std::string(1, bytes[0]) +
154 " in HTTP method name");
157 context_->method_.push_back(bytes[0]);
169 HttpRequestParser::httpMethodHandler() {
178 " in HTTP method name");
183 context_->method_.push_back(c);
190 HttpRequestParser::uriHandler() {
196 }
else if (
isCtl(c)) {
202 context_->uri_.push_back(c);
209 HttpRequestParser::versionHTTPHandler(
const char expected_letter,
210 const unsigned int next_state) {
212 [
this, expected_letter, next_state](
const char c) {
214 if (c == expected_letter) {
219 context_->http_version_major_ = 0;
220 context_->http_version_minor_ = 0;
227 parseFailure(
"unexpected character " + std::string(1, c) +
228 " in HTTP version string");
234 HttpRequestParser::versionNumberStartHandler(
const unsigned int next_state,
235 unsigned int* storage) {
237 [
this, next_state, storage](
const char c)
mutable {
241 *storage = *storage * 10 + c -
'0';
252 HttpRequestParser::versionNumberHandler(
const char following_character,
253 const unsigned int next_state,
254 unsigned int*
const storage) {
256 [
this, following_character, next_state, storage](
const char c)
260 if (c == following_character) {
263 }
else if (isdigit(c)) {
265 *storage = *storage * 10 + c -
'0';
275 HttpRequestParser::expectingNewLineHandler(
const unsigned int next_state) {
291 uint64_t content_length =
293 if (content_length > 0) {
297 }
catch (
const std::exception& ex) {
322 HttpRequestParser::headerLineStartHandler() {
329 }
else if (!context_->headers_.empty() && ((c ==
' ') || (c ==
'\t'))) {
340 context_->headers_.push_back(HttpHeaderContext());
341 context_->headers_.back().name_.push_back(c);
348 HttpRequestParser::headerLwsHandler() {
355 }
else if ((c ==
' ') || (c ==
'\t')) {
360 }
else if (
isCtl(c)) {
361 parseFailure(
"control character found in the HTTP header " +
362 context_->headers_.back().name_);
366 context_->headers_.back().value_.push_back(c);
373 HttpRequestParser::headerNameHandler() {
381 " found in the HTTP header name");
385 context_->headers_.back().name_.push_back(c);
392 HttpRequestParser::spaceBeforeHeaderValueHandler() {
398 }
else if (c ==
'\r') {
403 }
else if (
isCtl(c)) {
404 parseFailure(
"control character found in the HTTP header "
405 + context_->headers_.back().name_);
409 context_->headers_.back().value_.push_back(c);
416 HttpRequestParser::headerValueHandler() {
423 }
else if (
isCtl(c)) {
424 parseFailure(
"control character found in the HTTP header "
425 + context_->headers_.back().name_);
429 context_->headers_.back().value_.push_back(c);
436 HttpRequestParser::bodyHandler() {
440 context_->body_ += body;
442 if (context_->body_.length() < content_length) {
443 transition(HTTP_BODY_ST, DATA_READ_OK_EVT);
447 if (context_->body_.length() > content_length) {
448 context_->body_.resize(content_length);