Adds immediate migration results
This commit is contained in:
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_
|
||||
Reference in new issue
Block a user