diff --git a/src/Startup.cpp b/src/Startup.cpp index 7289d88..cec7389 100644 --- a/src/Startup.cpp +++ b/src/Startup.cpp @@ -364,6 +364,19 @@ void set_headers(httplib::Response& res) { res.set_header("Access-Control-Request-Headers", "X-API-Version"); } +std::vector split_string(const std::string& s, const char delim) { + std::stringstream ss(s); + std::string item; + std::vector elems; + while (std::getline(ss, item, delim)) { + if (!item.empty()) { + elems.push_back(item); + } + } + + return elems; +} + void StartProxy() { std::thread proxy([&]() { httplib::Server HTTPProxy; @@ -371,44 +384,91 @@ void StartProxy() { { "User-Agent", "BeamMP-Launcher/" + GetVer() + GetPatch() }, { "Accept", "*/*" } }; - std::string pattern = "/:any1"; - for (int i = 2; i <= 4; i++) { - HTTPProxy.Get(pattern, [&](const httplib::Request& req, httplib::Response& res) { - httplib::Client cli("https://backend.beammp.com"); - 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")); - } - if (auto cli_res = cli.Get(req.path, headers); 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"); - } - }); + httplib::Client backend("https://backend.beammp.com"); + httplib::Client forum("https://forum.beammp.com"); - HTTPProxy.Post(pattern, [&](const httplib::Request& req, httplib::Response& res) { - httplib::Client cli("https://backend.beammp.com"); - set_headers(res); - if (req.has_header("X-BMP-Authentication")) { - headers.emplace("X-BMP-Authentication", PrivateKey); + 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 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") { + std::string username; + std::string avatar_size = "100"; + + if (1 < path.size()) + username = path[1]; + + if (path.size() > 2) { + try { + if (std::stoi(path[2]) > 0) + avatar_size = path[2]; + + } catch (std::exception&) {} } - if (req.has_header("X-API-Version")) { - headers.emplace("X-API-Version", req.get_header_value("X-API-Version")); - } - if (auto cli_res = cli.Post(req.path, headers, req.body, - req.get_header_value("Content-Type")); - 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"); - } - }); - pattern += "/:any" + std::to_string(i); - } + + auto summary_res = forum.Get("/u/" + username + ".json", headers); + nlohmann::json d = nlohmann::json::parse(summary_res->body, nullptr, false); + + if (d.contains("user")) { + auto user = d.at("user"); + auto avatar_link_json = user.at("avatar_template"); + + if (avatar_link_json.is_string()) { + auto avatar_link = avatar_link_json.get(); + 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); + } + } else + 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();