add MP.HttpsGET, MP.HttpsPOST

This commit is contained in:
Lion Kortlepel 2021-07-01 00:33:28 +02:00
parent 549517c518
commit 853b078124
No known key found for this signature in database
GPG Key ID: 4322FF2B4C71259B
3 changed files with 125 additions and 12 deletions

View File

@ -17,11 +17,14 @@ using tcp = net::ip::tcp; // from <boost/asio/ip/tcp.hpp>
std::string Http::GET(const std::string& host, int port, const std::string& target, unsigned int* status) {
try {
// Check command line arguments.
int version = 11;
// The io_context is required for all I/O
net::io_context ioc;
@ -67,6 +70,8 @@ std::string Http::GET(const std::string& host, int port, const std::string& targ
beast::flat_buffer buffer;
// Declare a container to hold the response
http::response<http::string_body> res;
@ -86,17 +91,18 @@ std::string Http::GET(const std::string& host, int port, const std::string& targ
*status = res.base().result_int();
}
// ignore ec
if (ec)
throw beast::system_error { ec };
// If we get here then the connection is closed gracefully
return std::string(res.body());
} catch (std::exception const& e) {
Application::Console().Write(__func__ + std::string(": ") + e.what());
return "-1";
return ErrorString;
}
}
std::string Http::POST(const std::string& host, const std::string& target, const std::unordered_map<std::string, std::string>& fields, const std::string& body, bool json, int* 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) {
try {
net::io_context io;
@ -110,7 +116,7 @@ std::string Http::POST(const std::string& host, const std::string& target, const
decltype(resolver)::results_type results;
auto try_connect_with_protocol = [&](tcp protocol) {
try {
results = resolver.resolve(protocol, host, std::to_string(443));
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() };
// FIXME: we could throw and crash, if we like
@ -189,6 +195,10 @@ std::string Http::POST(const std::string& host, const std::string& target, const
}
Sentry.SetContext("https-post-response-data", response_data);
if (status) {
*status = response.base().result_int();
}
std::stringstream result;
result << response;
@ -199,12 +209,13 @@ std::string Http::POST(const std::string& host, const std::string& target, const
// info(result.str());
std::string debug_response_str;
std::getline(result, debug_response_str);
//debug("POST " + host + target + ": " + debug_response_str);
return std::string(response.body());
} catch (const std::exception& e) {
Application::Console().Write(e.what());
return "-1";
Application::Console().Write(__func__ + std::string(": ") + e.what());
return ErrorString;
}
}

View File

@ -705,7 +705,7 @@ int lua_Register(lua_State* L) {
ClearStack(L);
}
} else {
SendError(Engine(), L, "Register wrong arguments expected string");
SendError(Engine(), L, "Wrong arguments to `Register`, expected string");
}
return 0;
}
@ -799,6 +799,106 @@ int lua_GetOSName(lua_State* L) {
return 1;
}
// status, body = HttpGET(host, port, target)
// example usage:
// send a GET https://example.com:443/index.html:
// status, body = MP.HttpGET("example.com", 443, "/index.html")
int lua_HttpsGET(lua_State* L) {
if (!lua_isstring(L, 1)) {
SendError(Engine(), L, "`HttpsGET` expects host (type string) as first argument.");
ClearStack(L);
return 0;
}
if (!lua_isnumber(L, 2)) {
SendError(Engine(), L, "`HttpsGET` expects port (type number) as second argument.");
ClearStack(L);
return 0;
}
if (!lua_isstring(L, 3)) {
SendError(Engine(), L, "`HttpsGET` expects target (type string) as third argument.");
ClearStack(L);
return 0;
}
auto Host = lua_tostring(L, 1);
auto Port = int(lua_tointeger(L, 2));
auto Target = lua_tostring(L, 3);
ClearStack(L);
unsigned int Status;
auto Body = Http::GET(Host, Port, Target, &Status);
lua_pushinteger(L, Status);
auto PrettyRemote = "https://" + std::string(Host) + ":" + std::to_string(Port) + std::string(Target);
if (Body == Http::ErrorString) {
SendError(Engine(), L, "HTTPS GET " + PrettyRemote + " failed status " + std::to_string(Status) + ". Check the console or log for more info.");
return 1;
} else {
debug("GET " + PrettyRemote + " completed status " + std::to_string(Status));
}
lua_pushstring(L, Body.c_str());
return 2;
}
// status, body = HttpsPOST(host, port, target, body, content_type)
int lua_HttpsPOST(lua_State* L) {
if (!lua_isstring(L, 1)) {
SendError(Engine(), L, "`HttpsPOST` expects host (type string) as 1. argument.");
ClearStack(L);
return 0;
}
if (!lua_isnumber(L, 2)) {
SendError(Engine(), L, "`HttpsPOST` expects port (type number) as 2. argument.");
ClearStack(L);
return 0;
}
if (!lua_isstring(L, 3)) {
SendError(Engine(), L, "`HttpsPOST` expects target (type string) as 3. argument.");
ClearStack(L);
return 0;
}
if (!lua_isstring(L, 4)) {
SendError(Engine(), L, "`HttpsPOST` expects body (type string) as 4. argument.");
ClearStack(L);
return 0;
}
if (!lua_isstring(L, 5)) {
SendError(Engine(), L, "`HttpsPOST` expects content_type (type string) as 5. argument.");
ClearStack(L);
return 0;
}
auto Host = lua_tostring(L, 1);
auto Port = int(lua_tointeger(L, 2));
auto Target = lua_tostring(L, 3);
auto RequestBody = lua_tostring(L, 4);
auto ContentType = lua_tostring(L, 5);
ClearStack(L);
// build fields
std::unordered_map<std::string, std::string> Fields;
unsigned int Status;
auto ResponseBody = Http::POST(Host, Port, Target, {}, RequestBody, ContentType, &Status);
lua_pushinteger(L, Status);
auto PrettyRemote = "https://" + std::string(Host) + ":" + std::to_string(Port) + std::string(Target);
if (ResponseBody == Http::ErrorString) {
SendError(Engine(), L, "HTTPS POST " + PrettyRemote + " failed status " + std::to_string(Status) + ". Check the console or log for more info.");
return 1;
} else {
debug("POST " + PrettyRemote + " completed status " + std::to_string(Status));
}
lua_pushstring(L, ResponseBody.c_str());
return 2;
}
void TLuaFile::Load() {
Assert(mLuaState);
luaL_openlibs(mLuaState);
@ -826,6 +926,8 @@ void TLuaFile::Load() {
LuaTable::InsertFunction(mLuaState, "Sleep", lua_Sleep);
LuaTable::InsertFunction(mLuaState, "Set", lua_Set);
LuaTable::InsertFunction(mLuaState, "GetOSName", lua_GetOSName);
LuaTable::InsertFunction(mLuaState, "HttpsGET", lua_HttpsGET);
LuaTable::InsertFunction(mLuaState, "HttpsPOST", lua_HttpsPOST);
LuaTable::End(mLuaState, "MP");
lua_register(mLuaState, "print", lua_Print);
@ -901,7 +1003,7 @@ void SendError(TLuaEngine& Engine, lua_State* L, const std::string& msg) {
TLuaFile& S = MaybeS.value();
a = fs::path(S.GetFileName()).filename().string();
}
warn(a + (" | Incorrect Call of ") + msg);
warn(a + (" | Error in MP Lua call: ") + msg);
}
void TLuaArg::PushArgs(lua_State* State) {

View File

@ -290,7 +290,7 @@ void TNetwork::Authentication(SOCKET TCPSock) {
json::Document AuthResponse;
AuthResponse.Parse(Rc.c_str());
if (Rc == "-1" || AuthResponse.HasParseError()) {
if (Rc == Http::ErrorString || AuthResponse.HasParseError()) {
ClientKick(*Client, "Invalid key! Please restart your game.");
return;
}