43 context_(response.context()) {
59HttpResponseParser::defineStates() {
65 std::bind(&HttpResponseParser::receiveStartHandler,
this));
68 std::bind(&HttpResponseParser::versionHTTPHandler,
this,
'T',
72 std::bind(&HttpResponseParser::versionHTTPHandler,
this,
'T',
76 std::bind(&HttpResponseParser::versionHTTPHandler,
this,
'P',
80 std::bind(&HttpResponseParser::versionHTTPHandler,
this,
'/',
84 std::bind(&HttpResponseParser::numberStartHandler,
this,
87 &context_->http_version_major_));
90 std::bind(&HttpResponseParser::numberHandler,
this,
93 &context_->http_version_major_));
96 std::bind(&HttpResponseParser::numberStartHandler,
this,
99 &context_->http_version_minor_));
102 std::bind(&HttpResponseParser::numberHandler,
this,
105 &context_->http_version_minor_));
108 std::bind(&HttpResponseParser::numberStartHandler,
this,
111 &context_->status_code_));
114 std::bind(&HttpResponseParser::numberHandler,
this,
117 &context_->status_code_));
120 std::bind(&HttpResponseParser::phraseStartHandler,
this));
123 std::bind(&HttpResponseParser::phraseHandler,
this));
126 std::bind(&HttpResponseParser::expectingNewLineHandler,
this,
130 std::bind(&HttpResponseParser::headerLineStartHandler,
this));
133 std::bind(&HttpResponseParser::headerLwsHandler,
this));
136 std::bind(&HttpResponseParser::headerNameHandler,
this));
139 std::bind(&HttpResponseParser::spaceBeforeHeaderValueHandler,
this));
142 std::bind(&HttpResponseParser::headerValueHandler,
this));
145 std::bind(&HttpResponseParser::expectingNewLineHandler,
this,
149 std::bind(&HttpResponseParser::expectingNewLineHandler,
this,
153 std::bind(&HttpResponseParser::bodyHandler,
this));
157HttpResponseParser::receiveStartHandler() {
163 if (bytes[0] ==
'H') {
167 parseFailure(
"unexpected first character " + std::string(1, bytes[0]) +
179HttpResponseParser::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");
204HttpResponseParser::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 " +
223HttpResponseParser::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 " +
247HttpResponseParser::phraseStartHandler() {
250 parseFailure(
"invalid first character " + std::string(1, c) +
253 context_->phrase_.push_back(c);
260HttpResponseParser::phraseHandler() {
270 context_->phrase_.push_back(c);
277HttpResponseParser::expectingNewLineHandler(
const unsigned int next_state) {
293 uint64_t content_length =
295 if (content_length > 0) {
301 }
catch (
const std::exception& ex) {
326HttpResponseParser::headerLineStartHandler() {
333 }
else if (!context_->headers_.empty() && ((c ==
' ') || (c ==
'\t'))) {
344 context_->headers_.push_back(HttpHeaderContext());
345 context_->headers_.back().name_.push_back(c);
352HttpResponseParser::headerLwsHandler() {
359 }
else if ((c ==
' ') || (c ==
'\t')) {
364 }
else if (
isCtl(c)) {
365 parseFailure(
"control character found in the HTTP header " +
366 context_->headers_.back().name_);
370 context_->headers_.back().value_.push_back(c);
377HttpResponseParser::headerNameHandler() {
385 " found in the HTTP header name");
389 context_->headers_.back().name_.push_back(c);
396HttpResponseParser::spaceBeforeHeaderValueHandler() {
402 }
else if (c ==
'\r') {
407 }
else if (
isCtl(c)) {
408 parseFailure(
"control character found in the HTTP header "
409 + context_->headers_.back().name_);
413 context_->headers_.back().value_.push_back(c);
420HttpResponseParser::headerValueHandler() {
427 }
else if (
isCtl(c)) {
428 parseFailure(
"control character found in the HTTP header "
429 + context_->headers_.back().name_);
433 context_->headers_.back().value_.push_back(c);
440HttpResponseParser::bodyHandler() {
444 context_->body_ += body;
446 if (context_->body_.length() < content_length) {
447 transition(HTTP_BODY_ST, DATA_READ_OK_EVT);
451 if (context_->body_.length() > content_length) {
452 context_->body_.resize(content_length);
Base class for the HTTP message parsers.
void getNextFromBuffer(std::string &bytes, const size_t limit=1)
Retrieves next bytes of data from the buffer.
static const int DATA_READ_OK_EVT
Chunk of data successfully read and parsed.
static const int NEED_MORE_DATA_EVT
Unable to proceed with parsing until new data is provided.
bool isSpecial(const signed char c) const
Checks if specified value is a special character.
void parseFailure(const std::string &error_msg)
Transition parser to failure state.
bool isChar(const signed char c) const
Checks if specified value is a character.
void stateWithReadHandler(const std::string &handler_name, std::function< void(const char c)> after_read_logic)
Generic parser handler which reads a single byte of data and parses it using specified callback funct...
void invalidEventError(const std::string &handler_name, const unsigned int event)
This method is called when invalid event occurred in a particular parser state.
static const int HTTP_PARSE_OK_ST
Parsing successfully completed.
void stateWithMultiReadHandler(const std::string &handler_name, std::function< void(const std::string &)> after_read_logic)
Generic parser handler which reads multiple bytes of data and parses it using specified callback func...
bool isCtl(const signed char c) const
Checks if specified value is a control value.
static const int HTTP_PARSE_OK_EVT
Parsing HTTP request successful.
virtual void defineStates() override
Defines states of the parser.
bool requiresBody() const
Checks if the body is required for the HTTP message.
uint64_t getHeaderValueAsUint64(const std::string &header_name) const
Returns a value of the specified HTTP header as number.
static const int EXPECTING_NEW_LINE1_ST
Parsing first new line (after HTTP status phrase).
HttpResponseParser(HttpResponse &response)
Constructor.
static const int HTTP_VERSION_T1_ST
Parsing first occurrence of "T" in "HTTP".
static const int HEADER_VALUE_ST
Parsing header value.
static const int HTTP_VERSION_MAJOR_START_ST
Starting to parse major HTTP version number.
static const int HTTP_BODY_ST
Parsing body of a HTTP message.
static const int HTTP_VERSION_T2_ST
Parsing second occurrence of "T" in "HTTP".
static const int HEADER_NAME_ST
Parsing header name.
void initModel()
Initialize the state model for parsing.
static const int HTTP_VERSION_H_ST
Parsing letter "H" of "HTTP".
static const int HTTP_STATUS_CODE_START_ST
Starting to parse HTTP status code.
static const int EXPECTING_NEW_LINE3_ST
Expecting second new line marking end of HTTP headers.
static const int RECEIVE_START_ST
State indicating a beginning of parsing.
static const int HTTP_VERSION_P_ST
Parsing letter "P" in "HTTP".
static const int HTTP_VERSION_MINOR_START_ST
Starting to parse minor HTTP version number.
static const int HEADER_LINE_START_ST
static const int HTTP_PHRASE_ST
Parsing HTTP status phrase.
static const int HEADER_LWS_ST
Parsing LWS (Linear White Space), i.e.
static const int SPACE_BEFORE_HEADER_VALUE_ST
Parsing space before header value.
static const int HTTP_VERSION_MAJOR_ST
Parsing major HTTP version number.
static const int HTTP_STATUS_CODE_ST
Parsing HTTP status code.
static const int EXPECTING_NEW_LINE2_ST
Expecting new line after parsing header value.
static const int HTTP_VERSION_MINOR_ST
Parsing minor HTTP version number.
static const int HTTP_VERSION_SLASH_ST
Parsing slash character in "HTTP/Y.X".
static const int HTTP_PHRASE_START_ST
Starting to parse HTTP status phrase.
Represents HTTP response message.
virtual void create()
Commits information held in the context into the response.
void initDictionaries()
Initializes the event and state dictionaries.
void postNextEvent(unsigned int event)
Sets the next event to the given event value.
void defineState(unsigned int value, const std::string &label, StateHandler handler, const StatePausing &state_pausing=STATE_PAUSE_NEVER)
Adds an state value and associated label to the set of states.
unsigned int getNextEvent() const
Fetches the model's next event.
void transition(unsigned int state, unsigned int event)
Sets up the model to transition into given state with a given event.
static const int START_EVT
Event issued to start the model execution.
void setState(unsigned int state)
Sets the current state to the given state value.
unsigned int getCurrState() const
Fetches the model's current state.
Defines the logger used by the top-level component of kea-lfc.