diff options
Diffstat (limited to 'src/lib/http/request.h')
-rw-r--r-- | src/lib/http/request.h | 312 |
1 files changed, 312 insertions, 0 deletions
diff --git a/src/lib/http/request.h b/src/lib/http/request.h new file mode 100644 index 0000000..014e6e4 --- /dev/null +++ b/src/lib/http/request.h @@ -0,0 +1,312 @@ +// Copyright (C) 2016-2022 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_H +#define HTTP_REQUEST_H + +#include <hooks/callout_handle_associate.h> +#include <http/basic_auth.h> +#include <http/http_message.h> +#include <http/request_context.h> +#include <boost/shared_ptr.hpp> +#include <cstdint> + +namespace isc { +namespace http { + +/// @brief Generic exception thrown by @ref HttpRequest class. +class HttpRequestError : public HttpMessageError { +public: + HttpRequestError(const char* file, size_t line, const char* what) : + HttpMessageError(file, line, what) { }; +}; + +class HttpRequest; + +/// @brief Pointer to the @ref HttpRequest object. +typedef boost::shared_ptr<HttpRequest> HttpRequestPtr; + +/// @brief Represents HTTP request message. +/// +/// This derivation of the @c HttpMessage class is specialized to represent +/// HTTP requests. This class provides two constructors for creating an inbound +/// and outbound request instance respectively. This class is associated with +/// an instance of the @c HttpRequestContext, which is used to provide request +/// specific values, such as: HTTP method, version, URI and headers. +/// +/// The derivations of this class provide specializations and specify the +/// HTTP methods, versions and headers supported/required in the specific use +/// cases. For example, the @c PostHttpRequest class derives from @c HttpRequest +/// and it requires that request uses POST method. The @c PostHttpRequestJson, +/// which derives from @c PostHttpRequest requires that the POST message +/// includes body holding a JSON structure and provides methods to parse the +/// JSON body. +/// +/// Objects of this class is used to record some parameters for access control: +/// - the remote address +/// - the use of TLS +/// - the first commonName of the SubjectName of the client certificate +/// - the first commonName of the IssuerName of the client certificate +/// - the user ID of the basic HTTP authentication +/// - a custom value +/// +/// Callouts are associated to the request. +class HttpRequest : public HttpMessage, public hooks::CalloutHandleAssociate { +public: + + /// @brief HTTP methods. + enum class Method { + HTTP_GET, + HTTP_POST, + HTTP_HEAD, + HTTP_PUT, + HTTP_DELETE, + HTTP_OPTIONS, + HTTP_CONNECT, + HTTP_METHOD_UNKNOWN + }; + + /// @brief Constructor for inbound HTTP request. + HttpRequest(); + + /// @brief Constructor for outbound HTTP request. + /// + /// The constructor always includes Host header in the request, regardless + /// of the HTTP version used. + /// + /// @param method HTTP method, e.g. POST. + /// @param uri URI. + /// @param version HTTP version. + /// @param host_header Host header to be included in the request. The default + /// is the empty Host header. + /// @param basic_auth Basic HTTP authentication credential. The default + /// is no authentication. + HttpRequest(const Method& method, const std::string& uri, const HttpVersion& version, + const HostHttpHeader& host_header = HostHttpHeader(), + const BasicHttpAuthPtr& basic_auth = BasicHttpAuthPtr()); + + /// @brief Returns pointer to the @ref HttpRequestContext. + /// + /// The context holds intermediate data for creating a request. The request + /// parser stores parsed raw data in the context. When parsing is finished, + /// the data are validated and committed into the @c HttpRequest. + /// + /// @return Pointer to the underlying @ref HttpRequestContext. + const HttpRequestContextPtr& context() const { + return (context_); + } + + /// @brief Returns remote address. + /// + /// @return remote address from HTTP connection + /// getRemote method. + std::string getRemote() const { + return (remote_); + } + + /// @brief Set remote address. + /// + /// @param remote Remote end-point address in textual form. + void setRemote(const std::string& remote) { + remote_ = remote; + } + + /// @brief Specifies an HTTP method allowed for the request. + /// + /// Allowed methods must be specified prior to calling @ref create method. + /// If no method is specified, all methods are supported. + /// + /// @param method HTTP method allowed for the request. + void requireHttpMethod(const HttpRequest::Method& method); + + /// @brief Commits information held in the context into the request. + /// + /// This function reads HTTP method, version and headers from the context + /// and validates their values. For the outbound messages, it automatically + /// appends Content-Length header to the request, based on the length of the + /// request body. + /// + /// @throw HttpRequestError if the parsed request doesn't meet the specified + /// requirements for it. + virtual void create(); + + /// @brief Completes creation of the HTTP request. + /// + /// This method marks the message as finalized. The outbound request may now be + /// sent over the TCP socket. The information from the inbound message may be + /// read, including the request body. + virtual void finalize(); + + /// @brief Reset the state of the object. + virtual void reset(); + + /// @brief Returns HTTP method of the request. + Method getMethod() const; + + /// @brief Returns HTTP request URI. + std::string getUri() const; + + + /// @brief Returns HTTP message body as string. + std::string getBody() const; + + /// @brief Returns HTTP method, URI and HTTP version as a string. + std::string toBriefString() const; + + /// @brief Returns HTTP message as string. + /// + /// This method is called to generate the outbound HTTP message. Make + /// sure to call @c finalize prior to calling this method. + virtual std::string toString() const; + + /// @brief Checks if the client has requested persistent connection. + /// + /// For the HTTP/1.0 case, the connection is persistent if the client has + /// included Connection: keep-alive header. For the HTTP/1.1 case, the + /// connection is assumed to be persistent unless Connection: close header + /// has been included. + /// + /// @return true if the client has requested persistent connection, false + /// otherwise. + bool isPersistent() const; + + /// Access control parameters: get/set methods. + + /// @brief Returns recorded TLS usage. + /// + /// @return recorded TLS usage. + bool getTls() const { + return (tls_); + } + + /// @brief Set (record) TLS usage. + /// + /// @param tls the TLS usage. + void setTls(bool tls) { + tls_ = tls; + } + + /// @brief Returns recorded subject name. + /// + /// @return recorded subject name. + std::string getSubject() const { + return (subject_); + } + + /// @brief Set (record) subject name. + /// + /// @param subject the subject name. + void setSubject(const std::string& subject) { + subject_ = subject; + } + + /// @brief Returns recorded issuer name. + /// + /// @return recorded issuer name. + std::string getIssuer() const { + return (issuer_); + } + + /// @brief Set (record) issuer name. + /// + /// @param issuer the issuer name. + void setIssuer(const std::string& issuer) { + issuer_ = issuer; + } + + /// @brief Returns recorded basic auth. + /// + /// @return recorded basic auth. + std::string getBasicAuth() const { + return (basic_auth_); + } + + /// @brief Set (record) basic auth. + /// + /// @param basic_auth the basic auth. + void setBasicAuth(const std::string& basic_auth) { + basic_auth_ = basic_auth; + } + + /// @brief Returns recorded custom name. + /// + /// @return recorded custom name. + std::string getCustom() const { + return (custom_); + } + + /// @brief Set (record) custom name. + /// + /// @param custom the custom name. + void setCustom(const std::string& custom) { + custom_ = custom; + } + + /// Access control parameters: Flags which indicate what information to record. + /// Remote address and TLS usage are always recorded. + + /// @brief Record subject name. + static bool recordSubject_; + + /// @brief Record issuer name. + static bool recordIssuer_; + + /// @brief Record basic auth. + static bool recordBasicAuth_; + +protected: + + /// @brief Converts HTTP method specified in textual format to @ref Method. + /// + /// @param method HTTP method specified in the textual format. This value + /// is case insensitive. + /// + /// @return HTTP method as enum. + /// @throw HttpRequestError if unknown method specified. + Method methodFromString(std::string method) const; + + /// @brief Converts HTTP method to string. + /// + /// @param method HTTP method specified as enum. + /// + /// @return HTTP method as string. + std::string methodToString(const HttpRequest::Method& method) const; + + /// @brief Set of required HTTP methods. + /// + /// If the set is empty, all methods are allowed. + std::set<Method> required_methods_; + + /// @brief HTTP method of the request. + Method method_; + + /// @brief Pointer to the @ref HttpRequestContext holding parsed + /// data. + HttpRequestContextPtr context_; + + /// @brief Remote address. + std::string remote_; + + /// @brief TLS usage. + bool tls_; + + /// @brief Subject name. + std::string subject_; + + /// @brief Issuer name. + std::string issuer_; + + /// @brief Basic auth. + std::string basic_auth_; + + /// @brief Custom name. + std::string custom_; +}; + +} +} + +#endif |