Files
qt-migration-legatus/qt6-after/qt6-migrated-legatus/include/rti/apputils/http/server/Request.hpp
T

233 lines
6.9 KiB
C++

/*
* (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_REQUEST_HPP
#define HTTP_SERVER_REQUEST_HPP
#include <string>
#include <cstring>
#include <CivetServer.h>
#include <civetweb.h>
#include "rti/apputils/StringBuffer.hpp"
#include "rti/apputils/http/common/Method.hpp"
#include "rti/apputils/http/common/HttpException.hpp"
namespace rti { namespace apputils { namespace http { namespace server {
/**
* @brief This class implements the Request to handle Requests, that is
* requests provided by the CivetWeb server.
*/
class Request {
public:
/**
* @brief Constructor of the Request. Retrieves information from the
* mg_request_info provided by CivetWeb's connection.
*
* @param conn Civetweb's connection.
*/
explicit Request(mg_connection *conn) : conn_(conn)
{ }
/**
* @brief Destructor of the Request class.
*/
~Request()
{ }
/**
* @brief Returns the URL of CivetWeb's request.
*
* @return URL of the HTTP request.
*/
const char *uri() const
{
const auto req = mg_get_request_info(conn_);
RTI_SERVICE_CHECK_CONDITION_W_EXTRA_INFO(
req != nullptr,
msg_server_error_get_request_info);
return req->local_uri;
}
/**
* @brief Gets a URI parameter given its name.
*
* @param value The value of the parameter.
* @param name of the parameter to be retrieved.
* @return Indicates whether the parameter was found.
*/
bool uri_param(std::string& value, const std::string& name) const
{
const auto req = mg_get_request_info(conn_);
RTI_SERVICE_CHECK_CONDITION_W_EXTRA_INFO(
req != nullptr,
msg_server_error_get_request_info);
if (req->query_string == nullptr) {
return false;
}
return CivetServer::getParam(req->query_string, name.c_str(), value);
}
/**
* @brief Constructs a map with the query parameters in a given URI.
*
* @param params Map with decoded names and values of all the query
* parameters in the URI.
* @return Boolean value indicating whether query parameters were retrieved
* or not.
*/
bool uri_params(StringMap& params) const
{
const auto req = mg_get_request_info(conn_);
RTI_SERVICE_CHECK_CONDITION_W_EXTRA_INFO(
req != nullptr,
msg_server_error_get_request_info);
if (req->query_string == nullptr) {
return false;
}
const auto query_string = req->query_string;
auto query_string_length = strlen(query_string);
auto i = std::size_t { 0 };
while (i < query_string_length) {
// Get Name
auto i0 = i;
while ((i < query_string_length) && query_string[i] != '='
&& query_string[i] != '&') {
i++;
}
auto name = std::string();
CivetServer::urlDecode(&query_string[i0], i - i0, name, true);
if (i < query_string_length && query_string[i] == '=') {
i++;
}
// Get Value
i0 = i;
while ((i < query_string_length) && query_string[i] != '&') {
i++;
}
auto value = std::string();
CivetServer::urlDecode(&query_string[i0], i - i0, value, true);
if (i < query_string_length && query_string[i] == '&') {
i++;
}
// Add key-value pair to the map
params[name] = value;
}
return true;
}
/**
* @brief Gets a URI header given its name.
*
* @param Name of the header to be retrieved.
* @return Gets the value of an HTTP header given its name.
*/
const char *get_header(const char *name) const
{
const char *value = mg_get_header(conn_, name);
RTI_SERVICE_CHECK_CONDITION_W_EXTRA_INFO(
value != nullptr,
msg_server_error_get_header);
return value;
}
/**
* @brief This method saves the body of the HTTP request in the body buffer.
*
* @param [out] Body of the HTTP request.
* @param [in,out] Length of the body of the HTTP request.
*/
void get_body(char *& body, size_t& body_length) const
{
auto mg_result = mg_read(conn_, body, body_length);
RTI_SERVICE_CHECK_CONDITION_W_EXTRA_INFO(
mg_result >= 0,
msg_server_error_read);
}
/**
* @brief Saves the body of the HTTP request in a string buffer.
*
* @param [out] Body of the HTTP request in StringBuffer.
*/
void get_body(StringBuffer& body) const
{
const auto body_length = get_body_length();
body.ensure_capacity(body_length + 1);
auto mg_result = mg_read(conn_, body.c_str_ptr(), body_length);
RTI_SERVICE_CHECK_CONDITION_W_EXTRA_INFO(
mg_result >= 0,
msg_server_error_read);
}
/**
* @brief Returns the length of the body of the HTTP request.
*
* @return Body length.
*/
size_t get_body_length() const
{
const auto req = mg_get_request_info(conn_);
RTI_SERVICE_CHECK_CONDITION_W_EXTRA_INFO(
req != nullptr,
msg_server_error_get_request_info);
auto content_length = req->content_length;
// Check that the content_length is not negative (except for GET,
// DELETE, and PUT operations) where it is permitted.
if ((content_length < 0) && (strcmp(req->request_method, "GET") != 0)
&& (strcmp(req->request_method, "DELETE") != 0)
&& (strcmp(req->request_method, "PUT") != 0)) {
RTI_THROW_HTTP_EXCEPTION(
StatusCode::bad_request,
&RTI_LOG_ANY_FAILURE_s,
"Content-length of the HTTP request is invalid.");
}
return content_length < 0 ? 0 : static_cast<size_t>(content_length);
}
/**
* @brief Returns the method of the HTTP request.
*
* @return Method of the HTTP request.
*/
Method get_http_method() const
{
const struct mg_request_info *req = mg_get_request_info(conn_);
RTI_SERVICE_CHECK_CONDITION_W_EXTRA_INFO(
req != nullptr,
msg_server_error_get_request_info);
return method_from_string(
req->request_method == nullptr ? "" : req->request_method);
}
private:
struct mg_connection *conn_;
};
}}}} // namespace rti::apputils::http::server
#endif // HTTP_SERVER_REQUEST_HPP