remove boost, add httplib, temporarily remove http* lua

This commit is contained in:
Lion Kortlepel
2021-11-07 23:54:33 +01:00
parent 1e305c3c90
commit 701a7feee3
11 changed files with 43 additions and 147 deletions

View File

@@ -1,134 +1,39 @@
#include "Http.h"
#include "Common.h"
#undef error
#include <boost/asio/connect.hpp>
#include <boost/asio/ip/tcp.hpp>
#include <boost/beast.hpp>
#include <boost/beast/ssl.hpp>
#include <map>
namespace beast = boost::beast; // from <boost/beast.hpp>
namespace http = beast::http; // from <boost/beast/http.hpp>
namespace net = boost::asio; // from <boost/asio.hpp>
namespace ssl = net::ssl; // from <boost/asio/ssl.hpp>
using tcp = net::ip::tcp; // from <boost/asio/ip/tcp.hpp>
#include <httplib.h>
std::string GenericRequest(http::verb verb, const std::string& host, int port, const std::string& target, const std::unordered_map<std::string, std::string>& fields, const std::string& body, const std::string& ContentType, unsigned int* status) {
try {
net::io_context io;
// TODO: Add sentry error handling back
// The SSL context is required, and holds certificates
ssl::context ctx(ssl::context::tlsv13);
ctx.set_verify_mode(ssl::verify_none);
tcp::resolver resolver(io);
beast::ssl_stream<beast::tcp_stream> stream(io, ctx);
decltype(resolver)::results_type results;
auto try_connect_with_protocol = [&](tcp protocol) {
try {
results = resolver.resolve(protocol, host, std::to_string(port));
if (!SSL_set_tlsext_host_name(stream.native_handle(), host.c_str())) {
boost::system::error_code ec { static_cast<int>(::ERR_get_error()), boost::asio::error::get_ssl_category() };
return false;
}
beast::get_lowest_layer(stream).connect(results);
} catch (const boost::system::system_error&) {
return false;
}
return true;
};
bool ok = try_connect_with_protocol(tcp::v4());
if (!ok) {
Application::Console().Write("[ERROR] failed to resolve or connect in POST " + host + target);
Sentry.AddErrorBreadcrumb("failed to resolve or connect to " + host + target, __FILE__, std::to_string(__LINE__)); // FIXME: this is ugly.
return "-1";
}
stream.handshake(ssl::stream_base::client);
http::request<http::string_body> req { verb, target, 11 /* http 1.1 */ };
req.set(http::field::host, host);
if (!body.empty()) {
if (!ContentType.empty()) {
req.set(http::field::content_type, ContentType); // "application/json"
// "application/x-www-form-urlencoded"
}
req.set(http::field::content_length, std::to_string(body.size()));
req.body() = body;
}
for (const auto& pair : fields) {
req.set(pair.first, pair.second);
}
std::unordered_map<std::string, std::string> request_data;
for (const auto& header : req.base()) {
// need to do explicit casts to convert string_view to string
// since string_view may not be null-terminated (and in fact isn't, here)
std::string KeyString(header.name_string());
std::string ValueString(header.value());
request_data[KeyString] = ValueString;
}
Sentry.SetContext("https-request-data", request_data);
std::stringstream oss;
oss << req;
beast::get_lowest_layer(stream).expires_after(std::chrono::seconds(5));
http::write(stream, req);
// used for reading
beast::flat_buffer buffer;
http::response<http::string_body> response;
http::read(stream, buffer, response);
std::unordered_map<std::string, std::string> response_data;
response_data["reponse-code"] = std::to_string(response.result_int());
std::string Http::GET(const std::string& host, int port, const std::string& target, unsigned int* status) {
httplib::SSLClient client(host, port);
client.enable_server_certificate_verification(false);
auto res = client.Get(target.c_str());
if (res) {
if (status) {
*status = response.result_int();
*status = res->status;
}
for (const auto& header : response.base()) {
// need to do explicit casts to convert string_view to string
// since string_view may not be null-terminated (and in fact isn't, here)
std::string KeyString(header.name_string());
std::string ValueString(header.value());
response_data[KeyString] = ValueString;
}
Sentry.SetContext("https-response-data", response_data);
if (status) {
*status = response.base().result_int();
}
std::stringstream result;
result << response;
beast::error_code ec;
stream.shutdown(ec);
// IGNORING ec
std::string debug_response_str;
std::getline(result, debug_response_str);
return std::string(response.body());
} catch (const std::exception& e) {
Application::Console().Write(__func__ + std::string(": ") + e.what());
Sentry.AddErrorBreadcrumb(e.what(), __FILE__, std::to_string(__LINE__)); // FIXME: this is ugly.
return res->body;
} else {
return Http::ErrorString;
}
}
std::string Http::GET(const std::string& host, int port, const std::string& target, unsigned int* status) {
return GenericRequest(http::verb::get, host, port, target, {}, {}, "", status);
}
std::string Http::POST(const std::string& host, int port, const std::string& target, const std::unordered_map<std::string, std::string>& fields, const std::string& body, const std::string& ContentType, unsigned int* status) {
return GenericRequest(http::verb::post, host, port, target, fields, body, ContentType, status);
std::string Http::POST(const std::string& host, int port, const std::string& target, const std::string& body, const std::string& ContentType, unsigned int* status) {
httplib::SSLClient client(host, port);
client.enable_server_certificate_verification(false);
auto res = client.Post(target.c_str(), body.c_str(), body.size(), ContentType.c_str());
if (res) {
if (status) {
*status = res->status;
}
return res->body;
} else {
return Http::ErrorString;
}
}
// RFC 2616, RFC 7231

View File

@@ -48,17 +48,17 @@ void THeartbeatThread::operator()() {
auto Target = "/heartbeat";
unsigned int ResponseCode = 0;
T = Http::POST(Application::GetBackendHostname(), 443, Target, {}, Body, "application/x-www-form-urlencoded", &ResponseCode);
T = Http::POST(Application::GetBackendHostname(), 443, Target, Body, "application/x-www-form-urlencoded", &ResponseCode);
if ((T.substr(0, 2) != "20" && ResponseCode != 200) || ResponseCode != 200) {
beammp_trace("got " + T + " from backend");
SentryReportError(Application::GetBackendHostname() + Target, ResponseCode);
std::this_thread::sleep_for(std::chrono::milliseconds(500));
T = Http::POST(Application::GetBackup1Hostname(), 443, Target, {}, Body, "application/x-www-form-urlencoded", &ResponseCode);
T = Http::POST(Application::GetBackup1Hostname(), 443, Target, Body, "application/x-www-form-urlencoded", &ResponseCode);
if ((T.substr(0, 2) != "20" && ResponseCode != 200) || ResponseCode != 200) {
SentryReportError(Application::GetBackup1Hostname() + Target, ResponseCode);
std::this_thread::sleep_for(std::chrono::milliseconds(500));
T = Http::POST(Application::GetBackup2Hostname(), 443, Target, {}, Body, "application/x-www-form-urlencoded", &ResponseCode);
T = Http::POST(Application::GetBackup2Hostname(), 443, Target, Body, "application/x-www-form-urlencoded", &ResponseCode);
if ((T.substr(0, 2) != "20" && ResponseCode != 200) || ResponseCode != 200) {
beammp_warn("Backend system refused server! Server will not show in the public server list.");

View File

@@ -446,16 +446,9 @@ TLuaEngine::StateThreadData::StateThreadData(const std::string& Name, std::atomi
mEngine->CancelEventTimers(EventName, mStateId);
});
MPTable.set_function("Set", &LuaAPI::MP::Set);
MPTable.set_function("HttpsGET", [&](const std::string& Host, int Port, const std::string& Target) -> std::tuple<int, std::string> {
unsigned Status;
auto Body = Http::GET(Host, Port, Target, &Status);
return { Status, Body };
});
MPTable.set_function("HttpsPOST", [&](const std::string& Host, int Port, const std::string& Target, const std::string& Body, const std::string& ContentType) -> std::tuple<int, std::string> {
unsigned Status;
auto ResponseBody = Http::POST(Host, Port, Target, {}, Body, ContentType, &Status);
return { Status, ResponseBody };
});
auto HttpTable = StateView.create_named_table("Http");
//HttpTable.set_function("CreateConnection", &LuaAPI::Http::CreateConnection);
MPTable.create_named("Settings",
"Debug", 0,
"Private", 1,

View File

@@ -241,7 +241,7 @@ void TNetwork::Authentication(const TConnection& ClientConnection) {
auto Target = "/pkToUser";
unsigned int ResponseCode = 0;
if (!Rc.empty()) {
Rc = Http::POST(Application::GetBackendUrlForAuth(), 443, Target, {}, RequestString, "application/json", &ResponseCode);
Rc = Http::POST(Application::GetBackendUrlForAuth(), 443, Target, RequestString, "application/json", &ResponseCode);
}
json::Document AuthResponse;