Adds immediate migration results
This commit is contained in:
2395 files changed
+357322
-2524
No files matched your search
@@ -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
|
||||
Reference in new issue
Block a user