42 context_(request_.context()) {
58HttpRequestParser::defineStates() {
64 std::bind(&HttpRequestParser::receiveStartHandler,
this));
67 std::bind(&HttpRequestParser::httpMethodHandler,
this));
70 std::bind(&HttpRequestParser::uriHandler,
this));
73 std::bind(&HttpRequestParser::versionHTTPHandler,
this,
'H',
77 std::bind(&HttpRequestParser::versionHTTPHandler,
this,
'T',
81 std::bind(&HttpRequestParser::versionHTTPHandler,
this,
'T',
85 std::bind(&HttpRequestParser::versionHTTPHandler,
this,
'P',
89 std::bind(&HttpRequestParser::versionHTTPHandler,
this,
'/',
93 std::bind(&HttpRequestParser::versionNumberStartHandler,
this,
95 &context_->http_version_major_));
98 std::bind(&HttpRequestParser::versionNumberHandler,
this,
100 &context_->http_version_major_));
103 std::bind(&HttpRequestParser::versionNumberStartHandler,
this,
105 &context_->http_version_minor_));
108 std::bind(&HttpRequestParser::versionNumberHandler,
this,
110 &context_->http_version_minor_));
113 std::bind(&HttpRequestParser::expectingNewLineHandler,
this,
117 std::bind(&HttpRequestParser::headerLineStartHandler,
this));
120 std::bind(&HttpRequestParser::headerLwsHandler,
this));
123 std::bind(&HttpRequestParser::headerNameHandler,
this));
126 std::bind(&HttpRequestParser::spaceBeforeHeaderValueHandler,
this));
129 std::bind(&HttpRequestParser::headerValueHandler,
this));
132 std::bind(&HttpRequestParser::expectingNewLineHandler,
this,
136 std::bind(&HttpRequestParser::expectingNewLineHandler,
this,
140 std::bind(&HttpRequestParser::bodyHandler,
this));
144HttpRequestParser::receiveStartHandler() {
153 parseFailure(
"invalid first character " + std::string(1, bytes[0]) +
154 " in HTTP method name");
157 context_->method_.push_back(bytes[0]);
169HttpRequestParser::httpMethodHandler() {
178 " in HTTP method name");
183 context_->method_.push_back(c);
190HttpRequestParser::uriHandler() {
196 }
else if (
isCtl(c)) {
202 context_->uri_.push_back(c);
209HttpRequestParser::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");
234HttpRequestParser::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';
252HttpRequestParser::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';
275HttpRequestParser::expectingNewLineHandler(
const unsigned int next_state) {
291 uint64_t content_length =
293 if (content_length > 0) {
299 }
catch (
const std::exception& ex) {
324HttpRequestParser::headerLineStartHandler() {
331 }
else if (!context_->headers_.empty() && ((c ==
' ') || (c ==
'\t'))) {
342 context_->headers_.push_back(HttpHeaderContext());
343 context_->headers_.back().name_.push_back(c);
350HttpRequestParser::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);
375HttpRequestParser::headerNameHandler() {
383 " found in the HTTP header name");
387 context_->headers_.back().name_.push_back(c);
394HttpRequestParser::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);
418HttpRequestParser::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);
438HttpRequestParser::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);
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 version number).
static const int HTTP_URI_ST
Parsing URI.
static const int HTTP_VERSION_MAJOR_ST
Parsing major HTTP version number.
static const int HTTP_VERSION_SLASH_ST
Parsing slash character in "HTTP/Y.X".
static const int SPACE_BEFORE_HEADER_VALUE_ST
Parsing space before header value.
static const int HTTP_BODY_ST
Parsing body of a HTTP message.
static const int HTTP_VERSION_MAJOR_START_ST
Starting to parse major HTTP version number.
static const int EXPECTING_NEW_LINE3_ST
Expecting second new line marking end of HTTP headers.
static const int HEADER_NAME_ST
Parsing header name.
static const int RECEIVE_START_ST
State indicating a beginning of parsing.
void initModel()
Initialize the state model for parsing.
static const int HEADER_LWS_ST
Parsing LWS (Linear White Space), i.e.
static const int HTTP_VERSION_MINOR_ST
Parsing minor HTTP version number.
static const int HEADER_LINE_START_ST
Starting to parse a header line.
static const int HTTP_VERSION_H_ST
Parsing letter "H" of "HTTP".
static const int HTTP_VERSION_MINOR_START_ST
Starting to parse minor HTTP version number.
static const int HTTP_METHOD_ST
Parsing HTTP method, e.g. GET, POST etc.
static const int HEADER_VALUE_ST
Parsing header value.
HttpRequestParser(HttpRequest &request)
Constructor.
static const int EXPECTING_NEW_LINE2_ST
Expecting new line after parsing header value.
static const int HTTP_VERSION_P_ST
Parsing letter "P" in "HTTP".
static const int HTTP_VERSION_T2_ST
Parsing second occurrence of "T" in "HTTP".
static const int HTTP_VERSION_T1_ST
Parsing first occurrence of "T" in "HTTP".
Represents HTTP request message.
virtual void create()
Commits information held in the context into the request.
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.