mirror of
https://github.com/BeamMP/BeamMP-Launcher.git
synced 2025-07-01 23:46:59 +00:00
Move HTTP Proxy and remove and relocate duplicate code
This commit is contained in:
parent
de3888618a
commit
452fc1e484
@ -14,7 +14,7 @@ public:
|
|||||||
static std::string Post(const std::string& IP, const std::string& Fields);
|
static std::string Post(const std::string& IP, const std::string& Fields);
|
||||||
static std::string Get(const std::string& IP);
|
static std::string Get(const std::string& IP);
|
||||||
static bool ProgressBar(size_t c, size_t t);
|
static bool ProgressBar(size_t c, size_t t);
|
||||||
|
static void StartProxy();
|
||||||
public:
|
public:
|
||||||
static bool isDownload;
|
static bool isDownload;
|
||||||
};
|
};
|
@ -14,8 +14,8 @@ void InitLauncher(int argc, char* argv[]);
|
|||||||
std::string GetEP(char* P = nullptr);
|
std::string GetEP(char* P = nullptr);
|
||||||
std::string GetGamePath();
|
std::string GetGamePath();
|
||||||
std::string GetVer();
|
std::string GetVer();
|
||||||
|
std::string GetPatch();
|
||||||
std::string GetEN();
|
std::string GetEN();
|
||||||
void StartProxy();
|
|
||||||
void ConfigInit();
|
void ConfigInit();
|
||||||
extern bool Dev;
|
extern bool Dev;
|
||||||
|
|
||||||
|
20
include/Utils.h
Normal file
20
include/Utils.h
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace Utils {
|
||||||
|
inline std::vector<std::string> Split(const std::string& String, const std::string& delimiter) {
|
||||||
|
std::vector<std::string> Val;
|
||||||
|
size_t pos;
|
||||||
|
std::string token, s = String;
|
||||||
|
while ((pos = s.find(delimiter)) != std::string::npos) {
|
||||||
|
token = s.substr(0, pos);
|
||||||
|
if (!token.empty())
|
||||||
|
Val.push_back(token);
|
||||||
|
s.erase(0, pos + delimiter.length());
|
||||||
|
}
|
||||||
|
if (!s.empty())
|
||||||
|
Val.push_back(s);
|
||||||
|
return Val;
|
||||||
|
};
|
||||||
|
};
|
@ -15,6 +15,9 @@
|
|||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
#include <nlohmann/json.hpp>
|
#include <nlohmann/json.hpp>
|
||||||
|
#include <Startup.h>
|
||||||
|
#include <Network/network.hpp>
|
||||||
|
#include <Utils.h>
|
||||||
|
|
||||||
void WriteHttpDebug(const httplib::Client& client, const std::string& method, const std::string& target, const httplib::Result& result) try {
|
void WriteHttpDebug(const httplib::Client& client, const std::string& method, const std::string& target, const httplib::Result& result) try {
|
||||||
const std::filesystem::path folder = ".https_debug";
|
const std::filesystem::path folder = ".https_debug";
|
||||||
@ -171,3 +174,127 @@ bool HTTP::Download(const std::string& IP, const std::string& Path) {
|
|||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void set_headers(httplib::Response& res) {
|
||||||
|
res.set_header("Access-Control-Allow-Origin", "*");
|
||||||
|
res.set_header("Access-Control-Request-Method", "POST, OPTIONS, GET");
|
||||||
|
res.set_header("Access-Control-Request-Headers", "X-API-Version");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void HTTP::StartProxy() {
|
||||||
|
std::thread proxy([&]() {
|
||||||
|
httplib::Server HTTPProxy;
|
||||||
|
httplib::Headers headers = {
|
||||||
|
{ "User-Agent", "BeamMP-Launcher/" + GetVer() + GetPatch() },
|
||||||
|
{ "Accept", "*/*" }
|
||||||
|
};
|
||||||
|
httplib::Client backend("https://backend.beammp.com");
|
||||||
|
httplib::Client forum("https://forum.beammp.com");
|
||||||
|
|
||||||
|
const std::string pattern = ".*";
|
||||||
|
|
||||||
|
auto handle_request = [&](const httplib::Request& req, httplib::Response& res) {
|
||||||
|
set_headers(res);
|
||||||
|
if (req.has_header("X-BMP-Authentication")) {
|
||||||
|
headers.emplace("X-BMP-Authentication", PrivateKey);
|
||||||
|
}
|
||||||
|
if (req.has_header("X-API-Version")) {
|
||||||
|
headers.emplace("X-API-Version", req.get_header_value("X-API-Version"));
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::vector<std::string> path = Utils::Split(req.path, "/");
|
||||||
|
|
||||||
|
httplib::Result cli_res;
|
||||||
|
const std::string method = req.method;
|
||||||
|
std::string host = "";
|
||||||
|
|
||||||
|
if (!path.empty())
|
||||||
|
host = path[0];
|
||||||
|
|
||||||
|
if (host == "backend") {
|
||||||
|
std::string remaining_path = req.path.substr(std::strlen("/backend"));
|
||||||
|
|
||||||
|
if (method == "GET")
|
||||||
|
cli_res = backend.Get(remaining_path, headers);
|
||||||
|
else if (method == "POST")
|
||||||
|
cli_res = backend.Post(remaining_path, headers);
|
||||||
|
|
||||||
|
} else if (host == "avatar") {
|
||||||
|
bool error = false;
|
||||||
|
std::string username;
|
||||||
|
std::string avatar_size = "100";
|
||||||
|
|
||||||
|
if (path.size() > 1) {
|
||||||
|
username = path[1];
|
||||||
|
} else {
|
||||||
|
error = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (path.size() > 2) {
|
||||||
|
try {
|
||||||
|
if (std::stoi(path[2]) > 0)
|
||||||
|
avatar_size = path[2];
|
||||||
|
|
||||||
|
} catch (std::exception&) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
httplib::Result summary_res;
|
||||||
|
|
||||||
|
if (!error) {
|
||||||
|
summary_res = forum.Get("/u/" + username + ".json", headers);
|
||||||
|
|
||||||
|
if (!summary_res || summary_res->status != 200) {
|
||||||
|
error = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!error) {
|
||||||
|
try {
|
||||||
|
nlohmann::json d = nlohmann::json::parse(summary_res->body, nullptr, false); // can fail with parse_error
|
||||||
|
|
||||||
|
auto user = d.at("user"); // can fail with out_of_range
|
||||||
|
auto avatar_link_json = user.at("avatar_template"); // can fail with out_of_range
|
||||||
|
|
||||||
|
auto avatar_link = avatar_link_json.get<std::string>();
|
||||||
|
size_t start_pos = avatar_link.find("{size}");
|
||||||
|
if (start_pos != std::string::npos)
|
||||||
|
avatar_link.replace(start_pos, std::strlen("{size}"), avatar_size);
|
||||||
|
|
||||||
|
cli_res = forum.Get(avatar_link, headers);
|
||||||
|
|
||||||
|
} catch (std::exception&) {
|
||||||
|
error = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (error) {
|
||||||
|
cli_res = forum.Get("/user_avatar/forum.beammp.com/user/0/0.png", headers);
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
res.set_content("Host not found", "text/plain");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cli_res) {
|
||||||
|
res.set_content(cli_res->body, cli_res->get_header_value("Content-Type"));
|
||||||
|
} else {
|
||||||
|
res.set_content(to_string(cli_res.error()), "text/plain");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
HTTPProxy.Get(pattern, [&](const httplib::Request& req, httplib::Response& res) {
|
||||||
|
handle_request(req, res);
|
||||||
|
});
|
||||||
|
|
||||||
|
HTTPProxy.Post(pattern, [&](const httplib::Request& req, httplib::Response& res) {
|
||||||
|
handle_request(req, res);
|
||||||
|
});
|
||||||
|
|
||||||
|
ProxyPort = HTTPProxy.bind_to_any_port("0.0.0.0");
|
||||||
|
debug("HTTP Proxy listening on port " + std::to_string(ProxyPort));
|
||||||
|
HTTPProxy.listen_after_bind();
|
||||||
|
});
|
||||||
|
proxy.detach();
|
||||||
|
}
|
||||||
|
@ -28,26 +28,11 @@
|
|||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <future>
|
#include <future>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <string>
|
|
||||||
#include <thread>
|
#include <thread>
|
||||||
#include <vector>
|
#include <Utils.h>
|
||||||
|
|
||||||
namespace fs = std::filesystem;
|
namespace fs = std::filesystem;
|
||||||
std::string ListOfMods;
|
std::string ListOfMods;
|
||||||
std::vector<std::string> Split(const std::string& String, const std::string& delimiter) {
|
|
||||||
std::vector<std::string> Val;
|
|
||||||
size_t pos;
|
|
||||||
std::string token, s = String;
|
|
||||||
while ((pos = s.find(delimiter)) != std::string::npos) {
|
|
||||||
token = s.substr(0, pos);
|
|
||||||
if (!token.empty())
|
|
||||||
Val.push_back(token);
|
|
||||||
s.erase(0, pos + delimiter.length());
|
|
||||||
}
|
|
||||||
if (!s.empty())
|
|
||||||
Val.push_back(s);
|
|
||||||
return Val;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CheckForDir() {
|
void CheckForDir() {
|
||||||
if (!fs::exists("Resources")) {
|
if (!fs::exists("Resources")) {
|
||||||
@ -247,7 +232,7 @@ void SyncResources(SOCKET Sock) {
|
|||||||
info("Checking Resources...");
|
info("Checking Resources...");
|
||||||
CheckForDir();
|
CheckForDir();
|
||||||
|
|
||||||
std::vector<std::string> list = Split(Ret, ";");
|
std::vector<std::string> list = Utils::Split(Ret, ";");
|
||||||
std::vector<std::string> FNames(list.begin(), list.begin() + (list.size() / 2));
|
std::vector<std::string> FNames(list.begin(), list.begin() + (list.size() / 2));
|
||||||
std::vector<std::string> FSizes(list.begin() + (list.size() / 2), list.end());
|
std::vector<std::string> FSizes(list.begin() + (list.size() / 2), list.end());
|
||||||
list.clear();
|
list.clear();
|
||||||
|
136
src/Startup.cpp
136
src/Startup.cpp
@ -357,139 +357,3 @@ void PreGame(const std::string& GamePath) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void set_headers(httplib::Response& res) {
|
|
||||||
res.set_header("Access-Control-Allow-Origin", "*");
|
|
||||||
res.set_header("Access-Control-Request-Method", "POST, OPTIONS, GET");
|
|
||||||
res.set_header("Access-Control-Request-Headers", "X-API-Version");
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<std::string> split_string(const std::string& s, const char delim) {
|
|
||||||
std::stringstream ss(s);
|
|
||||||
std::string item;
|
|
||||||
std::vector<std::string> elems;
|
|
||||||
while (std::getline(ss, item, delim)) {
|
|
||||||
if (!item.empty()) {
|
|
||||||
elems.push_back(item);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return elems;
|
|
||||||
}
|
|
||||||
|
|
||||||
void StartProxy() {
|
|
||||||
std::thread proxy([&]() {
|
|
||||||
httplib::Server HTTPProxy;
|
|
||||||
httplib::Headers headers = {
|
|
||||||
{ "User-Agent", "BeamMP-Launcher/" + GetVer() + GetPatch() },
|
|
||||||
{ "Accept", "*/*" }
|
|
||||||
};
|
|
||||||
httplib::Client backend("https://backend.beammp.com");
|
|
||||||
httplib::Client forum("https://forum.beammp.com");
|
|
||||||
|
|
||||||
const std::string pattern = ".*";
|
|
||||||
|
|
||||||
auto handle_request = [&](const httplib::Request& req, httplib::Response& res) {
|
|
||||||
set_headers(res);
|
|
||||||
if (req.has_header("X-BMP-Authentication")) {
|
|
||||||
headers.emplace("X-BMP-Authentication", PrivateKey);
|
|
||||||
}
|
|
||||||
if (req.has_header("X-API-Version")) {
|
|
||||||
headers.emplace("X-API-Version", req.get_header_value("X-API-Version"));
|
|
||||||
}
|
|
||||||
|
|
||||||
const std::vector<std::string> path = split_string(req.path, '/');
|
|
||||||
|
|
||||||
httplib::Result cli_res;
|
|
||||||
const std::string method = req.method;
|
|
||||||
std::string host = "";
|
|
||||||
|
|
||||||
if (!path.empty())
|
|
||||||
host = path[0];
|
|
||||||
|
|
||||||
if (host == "backend") {
|
|
||||||
std::string remaining_path = req.path.substr(std::strlen("/backend"));
|
|
||||||
|
|
||||||
if (method == "GET")
|
|
||||||
cli_res = backend.Get(remaining_path, headers);
|
|
||||||
else if (method == "POST")
|
|
||||||
cli_res = backend.Post(remaining_path, headers);
|
|
||||||
|
|
||||||
} else if (host == "avatar") {
|
|
||||||
bool error = false;
|
|
||||||
std::string username;
|
|
||||||
std::string avatar_size = "100";
|
|
||||||
|
|
||||||
if (path.size() > 1) {
|
|
||||||
username = path[1];
|
|
||||||
} else {
|
|
||||||
error = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (path.size() > 2) {
|
|
||||||
try {
|
|
||||||
if (std::stoi(path[2]) > 0)
|
|
||||||
avatar_size = path[2];
|
|
||||||
|
|
||||||
} catch (std::exception&) {}
|
|
||||||
}
|
|
||||||
|
|
||||||
httplib::Result summary_res;
|
|
||||||
|
|
||||||
if (!error) {
|
|
||||||
summary_res = forum.Get("/u/" + username + ".json", headers);
|
|
||||||
|
|
||||||
if (!summary_res || summary_res->status != 200) {
|
|
||||||
error = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!error) {
|
|
||||||
try {
|
|
||||||
nlohmann::json d = nlohmann::json::parse(summary_res->body, nullptr, false); // can fail with parse_error
|
|
||||||
|
|
||||||
auto user = d.at("user"); // can fail with out_of_range
|
|
||||||
auto avatar_link_json = user.at("avatar_template"); // can fail with out_of_range
|
|
||||||
|
|
||||||
auto avatar_link = avatar_link_json.get<std::string>();
|
|
||||||
size_t start_pos = avatar_link.find("{size}");
|
|
||||||
if (start_pos != std::string::npos)
|
|
||||||
avatar_link.replace(start_pos, std::strlen("{size}"), avatar_size);
|
|
||||||
|
|
||||||
cli_res = forum.Get(avatar_link, headers);
|
|
||||||
|
|
||||||
} catch (std::exception&) {
|
|
||||||
error = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (error) {
|
|
||||||
cli_res = forum.Get("/user_avatar/forum.beammp.com/user/0/0.png", headers);
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
res.set_content("Host not found", "text/plain");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cli_res) {
|
|
||||||
res.set_content(cli_res->body, cli_res->get_header_value("Content-Type"));
|
|
||||||
} else {
|
|
||||||
res.set_content(to_string(cli_res.error()), "text/plain");
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
HTTPProxy.Get(pattern, [&](const httplib::Request& req, httplib::Response& res) {
|
|
||||||
handle_request(req, res);
|
|
||||||
});
|
|
||||||
|
|
||||||
HTTPProxy.Post(pattern, [&](const httplib::Request& req, httplib::Response& res) {
|
|
||||||
handle_request(req, res);
|
|
||||||
});
|
|
||||||
|
|
||||||
ProxyPort = HTTPProxy.bind_to_any_port("0.0.0.0");
|
|
||||||
debug("HTTP Proxy listening on port " + std::to_string(ProxyPort));
|
|
||||||
HTTPProxy.listen_after_bind();
|
|
||||||
});
|
|
||||||
proxy.detach();
|
|
||||||
}
|
|
||||||
|
@ -36,7 +36,7 @@ int main(int argc, char* argv[]) {
|
|||||||
fatal("Main 1 : " + std::string(e.what()));
|
fatal("Main 1 : " + std::string(e.what()));
|
||||||
}
|
}
|
||||||
|
|
||||||
StartProxy();
|
HTTP::StartProxy();
|
||||||
PreGame(GetGameDir());
|
PreGame(GetGameDir());
|
||||||
InitGame(GetGameDir());
|
InitGame(GetGameDir());
|
||||||
CoreNetwork();
|
CoreNetwork();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user