summaryrefslogtreecommitdiffstats
path: root/src/lib/http/request_parser.h
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-13 12:15:43 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-13 12:15:43 +0000
commitf5f56e1a1c4d9e9496fcb9d81131066a964ccd23 (patch)
tree49e44c6f87febed37efb953ab5485aa49f6481a7 /src/lib/http/request_parser.h
parentInitial commit. (diff)
downloadisc-kea-f5f56e1a1c4d9e9496fcb9d81131066a964ccd23.tar.xz
isc-kea-f5f56e1a1c4d9e9496fcb9d81131066a964ccd23.zip
Adding upstream version 2.4.1.upstream/2.4.1upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/lib/http/request_parser.h')
-rw-r--r--src/lib/http/request_parser.h246
1 files changed, 246 insertions, 0 deletions
diff --git a/src/lib/http/request_parser.h b/src/lib/http/request_parser.h
new file mode 100644
index 0000000..4f415d0
--- /dev/null
+++ b/src/lib/http/request_parser.h
@@ -0,0 +1,246 @@
+// Copyright (C) 2016-2018,2021 Internet Systems Consortium, Inc. ("ISC")
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#ifndef HTTP_REQUEST_PARSER_H
+#define HTTP_REQUEST_PARSER_H
+
+#include <http/http_message_parser_base.h>
+#include <http/request.h>
+#include <boost/shared_ptr.hpp>
+
+namespace isc {
+namespace http {
+
+class HttpRequestParser;
+
+/// @brief Pointer to the @ref HttpRequestParser.
+typedef boost::shared_ptr<HttpRequestParser> HttpRequestParserPtr;
+
+/// @brief A generic parser for HTTP requests.
+///
+/// This class implements a parser for HTTP requests. The parser derives from
+/// @ref HttpMessageParserBase class and implements its own state machine on
+/// top of it. The states of the parser reflect various parts of the HTTP
+/// message being parsed, e.g. parsing HTTP method, parsing URI, parsing
+/// message body etc. The descriptions of all parser states are provided
+/// below together with the constants defining these states.
+///
+/// The request parser validates the syntax of the received message as it
+/// progresses with parsing the data. Though, it doesn't interpret the received
+/// data until the whole message is parsed. In most cases we want to apply some
+/// restrictions on the message content, e.g. Kea Control API requires that
+/// commands are sent using HTTP POST, with a JSON command being carried in a
+/// message body. The parser doesn't verify if the message meets these
+/// restrictions until the whole message is parsed, i.e. stored in the
+/// @ref HttpRequestContext object. This object is associated with a
+/// @ref HttpRequest object (or its derivation). When the parsing is completed,
+/// the @ref HttpRequest::create method is called to retrieve the data from
+/// the @ref HttpRequestContext and interpret the data. In particular, the
+/// @ref HttpRequest or its derivation checks if the received message meets
+/// desired restrictions.
+///
+/// Kea Control API uses @ref PostHttpRequestJson class (which derives from the
+/// @ref HttpRequest) to interpret received request. This class requires
+/// that the HTTP request uses POST method and contains the following headers:
+/// - Content-Type: application/json,
+/// - Content-Length
+///
+/// If any of these restrictions is not met in the received message, an
+/// exception will be thrown, thereby @ref HttpRequestParser will fail parsing
+/// the message.
+class HttpRequestParser : public HttpMessageParserBase {
+public:
+
+ /// @name States supported by the HttpRequestParser.
+ ///
+ //@{
+
+ /// @brief State indicating a beginning of parsing.
+ static const int RECEIVE_START_ST = SM_DERIVED_STATE_MIN + 1;
+
+ /// @brief Parsing HTTP method, e.g. GET, POST etc.
+ static const int HTTP_METHOD_ST = SM_DERIVED_STATE_MIN + 2;
+
+ /// @brief Parsing URI.
+ static const int HTTP_URI_ST = SM_DERIVED_STATE_MIN + 3;
+
+ /// @brief Parsing letter "H" of "HTTP".
+ static const int HTTP_VERSION_H_ST = SM_DERIVED_STATE_MIN + 4;
+
+ /// @brief Parsing first occurrence of "T" in "HTTP".
+ static const int HTTP_VERSION_T1_ST = SM_DERIVED_STATE_MIN + 5;
+
+ /// @brief Parsing second occurrence of "T" in "HTTP".
+ static const int HTTP_VERSION_T2_ST = SM_DERIVED_STATE_MIN + 6;
+
+ /// @brief Parsing letter "P" in "HTTP".
+ static const int HTTP_VERSION_P_ST = SM_DERIVED_STATE_MIN + 7;
+
+ /// @brief Parsing slash character in "HTTP/Y.X"
+ static const int HTTP_VERSION_SLASH_ST = SM_DERIVED_STATE_MIN + 8;
+
+ /// @brief Starting to parse major HTTP version number.
+ static const int HTTP_VERSION_MAJOR_START_ST = SM_DERIVED_STATE_MIN + 9;
+
+ /// @brief Parsing major HTTP version number.
+ static const int HTTP_VERSION_MAJOR_ST = SM_DERIVED_STATE_MIN + 10;
+
+ /// @brief Starting to parse minor HTTP version number.
+ static const int HTTP_VERSION_MINOR_START_ST = SM_DERIVED_STATE_MIN + 11;
+
+ /// @brief Parsing minor HTTP version number.
+ static const int HTTP_VERSION_MINOR_ST = SM_DERIVED_STATE_MIN + 12;
+
+ /// @brief Parsing first new line (after HTTP version number).
+ static const int EXPECTING_NEW_LINE1_ST = SM_DERIVED_STATE_MIN + 13;
+
+ /// @brief Starting to parse a header line.
+ static const int HEADER_LINE_START_ST = SM_DERIVED_STATE_MIN + 14;
+
+ /// @brief Parsing LWS (Linear White Space), i.e. new line with a space
+ /// or tab character while parsing a HTTP header.
+ static const int HEADER_LWS_ST = SM_DERIVED_STATE_MIN + 15;
+
+ /// @brief Parsing header name.
+ static const int HEADER_NAME_ST = SM_DERIVED_STATE_MIN + 16;
+
+ /// @brief Parsing space before header value.
+ static const int SPACE_BEFORE_HEADER_VALUE_ST = SM_DERIVED_STATE_MIN + 17;
+
+ /// @brief Parsing header value.
+ static const int HEADER_VALUE_ST = SM_DERIVED_STATE_MIN + 18;
+
+ /// @brief Expecting new line after parsing header value.
+ static const int EXPECTING_NEW_LINE2_ST = SM_DERIVED_STATE_MIN + 19;
+
+ /// @brief Expecting second new line marking end of HTTP headers.
+ static const int EXPECTING_NEW_LINE3_ST = SM_DERIVED_STATE_MIN + 20;
+
+ /// @brief Parsing body of a HTTP message.
+ static const int HTTP_BODY_ST = SM_DERIVED_STATE_MIN + 21;
+
+ //@}
+
+
+ /// @brief Constructor.
+ ///
+ /// Creates new instance of the parser.
+ ///
+ /// @param request Reference to the @ref HttpRequest object or its
+ /// derivation that should be used to validate the parsed request and
+ /// to be used as a container for the parsed request.
+ explicit HttpRequestParser(HttpRequest& request);
+
+ /// @brief Initialize the state model for parsing.
+ ///
+ /// This method must be called before parsing the request, i.e. before
+ /// calling @ref HttpRequestParser::poll. It initializes dictionaries of
+ /// states and events, and sets the initial model state to RECEIVE_START_ST.
+ void initModel();
+
+private:
+
+ /// @brief Defines states of the parser.
+ virtual void defineStates();
+
+ /// @name State handlers.
+ ///
+ //@{
+
+ /// @brief Handler for RECEIVE_START_ST.
+ void receiveStartHandler();
+
+ /// @brief Handler for HTTP_METHOD_ST.
+ void httpMethodHandler();
+
+ /// @brief Handler for HTTP_URI_ST.
+ void uriHandler();
+
+ /// @brief Handler for states parsing "HTTP" string within the first line
+ /// of the HTTP request.
+ ///
+ /// @param expected_letter One of the 'H', 'T', 'P'.
+ /// @param next_state A state to which the parser should transition after
+ /// parsing the character.
+ void versionHTTPHandler(const char expected_letter,
+ const unsigned int next_state);
+
+ /// @brief Handler for HTTP_VERSION_MAJOR_START_ST and
+ /// HTTP_VERSION_MINOR_START_ST.
+ ///
+ /// This handler calculates version number using the following equation:
+ /// @code
+ /// storage = storage * 10 + c - '0';
+ /// @endcode
+ ///
+ /// @param next_state State to which the parser should transition.
+ /// @param [out] storage Reference to a number holding current product of
+ /// parsing major or minor version number.
+ void versionNumberStartHandler(const unsigned int next_state,
+ unsigned int* storage);
+
+ /// @brief Handler for HTTP_VERSION_MAJOR_ST and HTTP_VERSION_MINOR_ST.
+ ///
+ /// This handler calculates version number using the following equation:
+ /// @code
+ /// storage = storage * 10 + c - '0';
+ /// @endcode
+ ///
+ /// @param following_character Character following the version number, i.e.
+ /// '.' for major version, \r for minor version.
+ /// @param next_state State to which the parser should transition.
+ /// @param [out] storage Pointer to a number holding current product of
+ /// parsing major or minor version number.
+ void versionNumberHandler(const char following_character,
+ const unsigned int next_state,
+ unsigned int* const storage);
+
+ /// @brief Handler for states related to new lines.
+ ///
+ /// If the next_state is HTTP_PARSE_OK_ST it indicates that the parsed
+ /// value is a 3rd new line within request HTTP message. In this case the
+ /// handler calls @ref HttpRequest::create to validate the received message
+ /// (excluding body). The handler then reads the "Content-Length" header to
+ /// check if the request contains a body. If the "Content-Length" is greater
+ /// than zero, the parser transitions to HTTP_BODY_ST. If the
+ /// "Content-Length" doesn't exist the parser transitions to
+ /// HTTP_PARSE_OK_ST.
+ ///
+ /// @param next_state A state to which parser should transition.
+ void expectingNewLineHandler(const unsigned int next_state);
+
+ /// @brief Handler for HEADER_LINE_START_ST.
+ void headerLineStartHandler();
+
+ /// @brief Handler for HEADER_LWS_ST.
+ void headerLwsHandler();
+
+ /// @brief Handler for HEADER_NAME_ST.
+ void headerNameHandler();
+
+ /// @brief Handler for SPACE_BEFORE_HEADER_VALUE_ST.
+ void spaceBeforeHeaderValueHandler();
+
+ /// @brief Handler for HEADER_VALUE_ST.
+ void headerValueHandler();
+
+ /// @brief Handler for HTTP_BODY_ST.
+ void bodyHandler();
+
+ //@}
+
+ /// @brief Reference to the request object specified in the constructor.
+ HttpRequest& request_;
+
+ /// @brief Pointer to the internal context of the @ref HttpRequest object.
+ HttpRequestContextPtr context_;
+};
+
+} // namespace http
+} // namespace isc
+
+#endif // HTTP_REQUEST_PARSER_H
+