/* * (c) Copyright, Real-Time Innovations, 2022. * All rights reserved. * * No duplications, whole or partial, manual or electronic, may be made * without express written permission. Any such copies, or * revisions thereof, must display this notice unaltered. * This code contains trade secrets of Real-Time Innovations, Inc. */ #ifndef HTTP_SERVER_PROPERTY_HPP #define HTTP_SERVER_PROPERTY_HPP #include #include #include #include "rti/apputils/util/Path.hpp" #include "rti/apputils/http/common/HttpUtils.hpp" namespace rti { namespace apputils { namespace http { namespace server { /** * @brief This class contains the HTTP server properties */ class ServerProperty { public: /** * @brief ServerProperty constructor */ ServerProperty(const std::string& ports = HTTP_SERVER_DEFAULT_PORT_STR) : handle_options_request_(false) { listening_ports(ports); } /** * @brief Destroy the Server Property object */ virtual ~ServerProperty() = default; /** * @brief Return the document root path. * * @return const std::string& */ const std::string& document_root() const { return document_root_; } /** * @brief Return the web server options. * * @return const std::vector& */ const std::vector& webserver_options() const { return webserver_options_; } /** * @brief Return the value of a web server options given it name. If the * option is not found, the name will be returned. * * @return const std::string>& option value, or option name if not found. */ const std::string& webserver_option(std::string& name) const { auto it = std::find( webserver_options_.begin(), webserver_options_.end(), name); if (it != webserver_options_.end() && ++it != webserver_options_.end()) { return *it; } return name; } /** * @brief This method returns true if the server will handle OPTIONS * requests, otherwise false. * * @return boolean */ bool handle_options_request() const { return handle_options_request_; } /** * @brief Set the document root path. * * @param document_root * @return ServerProperty& */ ServerProperty& document_root(const std::string& document_root) { if (!document_root.empty()) { document_root_ = util::Path(document_root); RTI_SERVICE_CHECK_CONDITION_W_EXTRA_INFO( document_root_.exists(), "Document root path does not exist"); set_webserver_option("document_root", document_root_.c_str()); } return *this; } /** * @brief Set the listening ports. * * @param listening_ports * @return ServerProperty& */ ServerProperty& listening_ports(const std::string& listening_ports) { listening_ports_ = listening_ports; set_webserver_option("listening_ports", listening_ports.c_str()); return *this; } /** * @brief This method enters a key-value pair into the webserver_options * array. * * @param key Name of the option to be set. * @param value Value of the option. */ ServerProperty& set_webserver_option(const char *key, const char *value) { // Check if the option already exists. auto it = std::find( webserver_options_.begin(), webserver_options_.end(), key); // if exists modify the value if (it != webserver_options_.end() && ++it != webserver_options_.end()) { *it = value; } else { // Add option name webserver_options_.emplace_back(key); // Add option value webserver_options_.emplace_back(value); } return *this; } /** * @brief This option enables the server to handle OPTIONS requests if true, * otherwise civetweb will handle them. * * @param handle_options_request boolean value to handle OPTIONS requests. * @return ServerProperty& */ ServerProperty& handle_options_request(bool handle_options_request) { handle_options_request_ = handle_options_request; return *this; } static std::string parse_port(const std::string& host) { std::string::size_type scheme_pos = host.find("://"); if (scheme_pos == std::string::npos) { RTI_THROW_SERVICE_EXCEPTION( &RTI_LOG_INIT_FAILURE_s, "Invalid scheme format"); } std::string unformatted_host = host.substr(scheme_pos + 1); std::string::size_type port_pos = unformatted_host.find(":"); if (port_pos == std::string::npos) { RTI_THROW_SERVICE_EXCEPTION( &RTI_LOG_INIT_FAILURE_s, "Invalid host:port format"); } std::string port_string = unformatted_host.substr(port_pos + 1); try { // Check that port has a valid format std::stoi(port_string); } catch (...) { std::string error_msg; error_msg.append("Invalid port value: ").append(port_string); RTI_THROW_SERVICE_EXCEPTION( &RTI_LOG_INIT_FAILURE_s, error_msg.c_str()); } return port_string; } private: // Server options util::Path document_root_; std::string listening_ports_; std::vector webserver_options_; bool handle_options_request_; }; }}}} // namespace rti::apputils::http::server #endif // HTTP_SERVER_PROPERTY_HPP