Adds immediate migration results

This commit is contained in:
torsten committed 2026-08-18 22:12:24 +02:00
1 parent ba4121728b
commit 6a2a0667ab
2395 files changed
+357322 -2524

No files matched your search

@@ -0,0 +1,74 @@
/*
* (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_EXCEPTION_HPP
#define HTTP_EXCEPTION_HPP
// RTI headers
#include "rti/apputils/http/common/StatusCode.hpp"
#include "rti/apputils/ServiceException.hpp"
namespace rti { namespace apputils { namespace http {
/**
* @brief Exception class for HTTP errors that inherit from ServiceException
*/
class HttpException : public ServiceException {
public:
/**
* @brief Constructor
*
* @param throwing_context The context where the exception was thrown
* @param status_code HTTP status code
* @param log_message RTILog message (it could be a format string)
*/
template <typename... Args>
HttpException(
const char *throwing_context,
StatusCode error_code,
const RTILogMessage *log_message,
Args... args)
: ServiceException(throwing_context, log_message, args...),
error_code_(error_code)
{ }
/**
* @brief Constructor
*
* @param ServiceException Service Exception to build the HttpException
* @param status_code HTTP status code
*/
HttpException(
const ServiceException& e,
StatusCode error_code)
: ServiceException(e),
error_code_(error_code)
{ }
/**
* @brief Get the HTTP status code
*
* @return HTTP status code
*/
StatusCode error_code() const
{
return error_code_;
}
private:
StatusCode error_code_;
};
}}} // namespace rti::apputils::http
#define RTI_THROW_HTTP_EXCEPTION(...) \
throw rti::apputils::http::HttpException(RTI_FUNCTION_NAME, __VA_ARGS__)
#endif // HTTP_EXCEPTION_HPP
@@ -0,0 +1,167 @@
/*
* (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_UTILS_H
#define HTTP_UTILS_H
#include <ctime>
#include <cstring>
#include <unordered_map>
#include <civetweb.h>
#include <reda/reda_string.h>
#include <dds_c/dds_c_printformat.h>
#include "HttpException.hpp"
#include "StatusCode.hpp"
namespace rti { namespace apputils { namespace http {
using StringMap = std::unordered_map<std::string, std::string>;
// Unfortunately Civetweb doesn't expose these constants, so we needed to
// copy the values from civetweb.c (static struct mg_option config_options[])
constexpr auto HTTP_CLIENT_TIMEOUT_MS = int { 1000 };
constexpr auto HTTP_SERVER_DEFAULT_PORT = int { 8080 };
constexpr auto HTTP_SERVER_DEFAULT_PORT_STR = "8080";
constexpr auto HTTP_SERVER_DEFAULT_HOST = "127.0.0.1";
constexpr auto HTTP_VERSION = "1.1";
constexpr auto HTTP_CACHE_CONTROL_NO_CACHE = "no-cache";
constexpr auto HTTP_BODY_INITIAL_LENGTH = std::size_t { 1000 };
constexpr auto HTTP_PLAIN_TEXT_CONTENT_TYPE = "text/plain";
constexpr auto HTTP_JSON_CONTENT_TYPE = "application/json";
constexpr auto HTTP_XML_CONTENT_TYPE = "application/xml";
constexpr auto HTTP_CONTENT_TYPE_HEADER = "Content-Type";
constexpr auto HTTP_DATE_STR_LENGTH = std::size_t { 64 };
/**
* Maximum URL length we handle is 2048. This value is based on the
* comments on this article http://stackoverflow.com/questions/417142
*/
constexpr auto MAX_URI_LENGTH = int { 2048 };
/**
* @brief This structure contains utility methods to generate HttpSettings that
* need to be set as part of the HTTP response.
*/
struct HttpSettings {
/**
* @brief This method converts time_t to a string. According to RFC2616,
* Sec 14.18, this must be included in all responses other than
* 100, 101, 5xx.
*
* @return A string containing the date in the format specified by RFC2616.
*/
static std::string get_current_date()
{
const auto curtime = std::time(nullptr);
if (curtime == (time_t) -1) {
return "Thu, 01 Jan 1970 00:00:00 GMT";
}
struct tm curr_tm;
#ifdef RTI_WIN32
if (gmtime_s(&curr_tm, &curtime) != 0) {
return "Thu, 01 Jan 1970 00:00:00 GMT";
}
#else
if (gmtime_r(&curtime, &curr_tm) != &curr_tm) {
return "Thu, 01 Jan 1970 00:00:00 GMT";
}
#endif
auto result = std::string(HTTP_DATE_STR_LENGTH, '\0');
const auto bytes_written = std::strftime(
&result[0],
result.size(),
"%a, %d %b %Y %H:%M:%S GMT",
&curr_tm);
RTI_SERVICE_CHECK_CONDITION_W_EXTRA_INFO(
bytes_written > 0,
"Error in std::strftime");
result.resize(bytes_written);
return result;
}
};
inline std::string read_content_with_content_length(
mg_connection *connection,
std::size_t content_length)
{
auto content = std::string(content_length, 0);
auto result = 0;
while (content_length > 0 && result >= 0) {
result = mg_read(connection,
&content[content.size() - content_length],
content_length);
content_length -= result;
}
return content;
}
inline std::string read_content_without_content_length(
mg_connection *connection,
std::size_t chunk_size = 256)
{
auto content = std::string();
auto bytes_read = std::size_t { 0 };
auto result = 0;
do {
bytes_read += result;
content.resize(bytes_read + chunk_size);
result = mg_read(connection, &content[bytes_read], chunk_size);
} while (result > 0);
content.resize(bytes_read);
return content;
}
inline std::string base64_encode(const std::string& in)
{
std::string out;
out.reserve(in.size() * 2);
const char *b64 =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
for (std::size_t i = 0; i < in.size(); i += 3) {
// Static cast to unsigned char to avoid cert_str34_c_violation
int a = static_cast<unsigned char>(in[i]);
int b = i + 1 >= in.size() ? 0 : static_cast<unsigned char>(in[i + 1]);
int c = i + 2 >= in.size() ? 0 : static_cast<unsigned char>(in[i + 2]);
out.push_back(b64[a >> 2]);
out.push_back(b64[((a & 3) << 4) | (b >> 4)]);
if (i + 1 < in.size()) {
out.push_back(b64[(b & 15) << 2 | (c >> 6)]);
}
if (i + 2 < in.size()) {
out.push_back(b64[c & 63]);
}
}
while (out.size() % 4 != 0) {
out.push_back('=');
}
out.shrink_to_fit();
return out;
}
}}} // namespace rti::apputils::http
#endif // HTTP_UTILS_H
@@ -0,0 +1,96 @@
/*
* (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_METHOD_HPP
#define HTTP_METHOD_HPP
#include <string>
#include "rti/apputils/http/common/HttpException.hpp"
namespace rti {
namespace apputils { namespace http {
/**
* Enum class with every HTTP method
*/
enum class Method {
http_post,
http_put,
http_get,
http_delete,
http_options,
http_head,
http_patch
};
/**
* @brief Convert a Method enum to an std::string
*
* @param http_method Method enum to convert
* @return std::string with the method name
*/
inline std::string method_to_string(Method http_method)
{
switch (http_method) {
case Method::http_post:
return "POST";
case Method::http_put:
return "PUT";
case Method::http_get:
return "GET";
case Method::http_delete:
return "DELETE";
case Method::http_options:
return "OPTIONS";
case Method::http_head:
return "HEAD";
case Method::http_patch:
return "PATCH";
default:
RTI_THROW_HTTP_EXCEPTION(
StatusCode::bad_request,
&RTI_LOG_ANY_FAILURE_s,
"Invalid HTTP method");
}
}
/**
* @brief Convert a std::string to a Method enum
*
* @param http_method String to convert
* @return Method enum
*/
inline Method method_from_string(const std::string& http_method)
{
if (http_method == "POST") {
return Method::http_post;
} else if (http_method == "PUT") {
return Method::http_put;
} else if (http_method == "GET") {
return Method::http_get;
} else if (http_method == "DELETE") {
return Method::http_delete;
} else if (http_method == "OPTIONS") {
return Method::http_options;
} else if (http_method == "HEAD") {
return Method::http_head;
} else if (http_method == "PATCH") {
return Method::http_patch;
} else {
RTI_THROW_HTTP_EXCEPTION(
StatusCode::bad_request,
&RTI_LOG_ANY_FAILURE_s,
"Invalid HTTP method");
}
}
}}} // namespace rti::apputils::http
#endif // HTTP_METHOD_HPP
@@ -0,0 +1,51 @@
/*
* (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_RESPONSE_HPP
#define HTTP_RESPONSE_HPP
#include <string>
#include <unordered_map>
namespace rti { namespace apputils { namespace http {
/**
* @brief This class contains all the elements involved in an HTTP response
*/
struct Response {
/**
* Response's status code
*/
unsigned short http_status_code;
/**
* Response's reason phrase
*/
std::string http_reason_phrase;
/**
* Response's content type
*/
std::string http_content_type;
/**
* Response's body
*/
std::string http_content;
/**
* Response's headers as a map
*/
std::unordered_map<std::string, std::string> http_headers;
};
}}} // namespace rti::apputils::http
#endif // HTTP_RESPONSE_HPP
@@ -0,0 +1,90 @@
/*
* (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_STATUS_CODE_HPP
#define HTTP_STATUS_CODE_HPP
#include <string>
namespace rti { namespace apputils { namespace http {
/**
* @brief Enum class with HTTP status codes.
*/
enum class StatusCode {
ok = 200,
created = 201,
accepted = 202,
no_content = 204,
multiple_choices = 300,
moved_permanently = 301,
moved_temporarily = 302,
not_modified = 304,
bad_request = 400,
unauthorized = 401,
forbidden = 403,
not_found = 404,
not_allowed = 405,
internal_server_error = 500,
not_implemented = 501,
bad_gateway = 502,
service_unavailable = 503
};
/**
* @brief Convert a StatusCode enum to an std::string
*
* @param status_code StatusCode enum to convert
* @return std::string with the status code name
*/
inline std::string status_code_to_string(StatusCode status_code)
{
switch (status_code) {
case StatusCode::ok:
return "OK";
case StatusCode::created:
return "Created";
case StatusCode::accepted:
return "Accepted";
case StatusCode::no_content:
return "No Content";
case StatusCode::multiple_choices:
return "Multiple Choices";
case StatusCode::moved_permanently:
return "Moved Permanently";
case StatusCode::moved_temporarily:
return "Moved Temporarily";
case StatusCode::not_modified:
return "Not Modified";
case StatusCode::bad_request:
return "Bad Request";
case StatusCode::unauthorized:
return "Unauthorized";
case StatusCode::forbidden:
return "Forbidden";
case StatusCode::not_found:
return "Not Found";
case StatusCode::not_allowed:
return "Not Allowed";
case StatusCode::internal_server_error:
return "Internal Server Error";
case StatusCode::not_implemented:
return "Not Implemented";
case StatusCode::bad_gateway:
return "Bad Gateway";
case StatusCode::service_unavailable:
return "Service Unavailable";
default:
return "";
}
}
}}} // namespace rti::apputils::http
#endif // HTTP_STATUS_CODE_HPP
@@ -0,0 +1,100 @@
/*
* (c) Copyright, Real-Time Innovations, 2024.
* 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 WEBSOCKET_API_UTILS_H_
#define WEBSOCKET_API_UTILS_H_
#include "dds_c/dds_c_printformat.h"
#include <memory>
#include <rti/apputils/http/common/HttpException.hpp>
#define ERR_LOST_HEADER "Lost header"
#define WEBSOCKET_RESPONSE_NAME "response"
#define WEBSOCKET_HELLO_FAIL_HEADER "HELLO FAIL:"
namespace rti { namespace apputils { namespace websocket {
enum class WebSocketStateKind{
UNKNOWN,
CREATE,
OPEN,
READY,
CLOSE
};
enum class WebSocketContentType{
UNKNOWN,
JSON,
XML
};
inline DDS_PrintFormatKind to_print_format_kind(WebSocketContentType contentType) {
return contentType == WebSocketContentType::JSON
? DDS_JSON_PRINT_FORMAT
: DDS_XML_PRINT_FORMAT;
}
inline WebSocketContentType to_websocket_content_type(DDS_PrintFormatKind formatKind) {
WebSocketContentType value = WebSocketContentType::UNKNOWN;
switch (formatKind) {
case DDS_JSON_PRINT_FORMAT:
value = WebSocketContentType::JSON;
break;
case DDS_XML_PRINT_FORMAT:
value = WebSocketContentType::XML;
break;
case DDS_DEFAULT_PRINT_FORMAT:
value = WebSocketContentType::XML;
break;
default:
value = WebSocketContentType::UNKNOWN;
break;
}
return value;
}
/**
* The RequestException class defines a exception will log an error message
* via RTIWsddsLog_exeption or will just propagate a given return code
* identifying the error and an error message. The class inherits from
* Exception, as a result users can use familiar interfaces, such as what() to
* get the error message. Also it have the request id to create the error
* message to be sent.
*/
class RequestException : public rti::apputils::http::HttpException {
public:
RequestException(
const char *throwing_context,
rti::apputils::http::StatusCode error_code,
const RTILogMessage *log_message,
const char *method_name,
...)
: HttpException(throwing_context, error_code, log_message),
method_name_(method_name)
{
}
/**
* Returns the method name that threw the exception.
* @return Method name that threw the exception.
*/
const char * get_method_name() const
{
return method_name_;
}
private:
const char *method_name_;
};
}}} // namespace rti::webdds::websocket
#endif // WEBSOCKET_API_UTILS_H_