#include "sidecar_api.h" #include "../../common/http/httplib.h" #include "../../common/eqemu_logsys.h" #include "../zonedb.h" #include "../../common/process.h" #include "../common.h" #include "../zone.h" #include "../client.h" #include "../../common/json/json.hpp" #include void CatchSidecarSignal(int sig_num) { LogInfo("[SidecarAPI] Caught signal [{}]", sig_num); LogInfo("Forcefully exiting for now"); std::exit(0); } #include "log_handler.cpp" #include "test_controller.cpp" #include "map_best_z_controller.cpp" #include "../../common/file.h" constexpr static int HTTP_RESPONSE_OK = 200; constexpr static int HTTP_RESPONSE_BAD_REQUEST = 400; constexpr static int HTTP_RESPONSE_UNAUTHORIZED = 401; std::string authorization_key; void SidecarApi::BootWebserver(int port, const std::string &key) { LogInfo("Booting zone sidecar API"); std::signal(SIGINT, CatchSidecarSignal); std::signal(SIGTERM, CatchSidecarSignal); std::signal(SIGKILL, CatchSidecarSignal); if (!key.empty()) { authorization_key = key; LogInfo("Booting with authorization key [{}]", authorization_key); } int web_api_port = port > 0 ? port : 9099; std::string hotfix_name = "zonesidecar_api_"; // bake shared memory if it doesn't exist // TODO: Windows if (!File::Exists("shared/zonesidecar_api_loot_drop")) { LogInfo("Creating shared memory for prefix [{}]", hotfix_name); std::string output = Process::execute( fmt::format( "./bin/shared_memory -hotfix={} loot items", hotfix_name ) ); std::cout << output << "\n"; } // bootup a fake zone Zone::Bootup(ZoneID("qrg"), 0, false); zone->StopShutdownTimer(); httplib::Server api; api.set_logger(SidecarApi::RequestLogHandler); api.set_pre_routing_handler( [](const auto &req, auto &res) { for (const auto &header: req.headers) { auto header_key = header.first; auto header_value = header.second; LogHTTPDetail("[API] header_key [{}] header_value [{}]", header_key, header_value); if (header_key == "Authorization") { std::string auth_key = header_value; Strings::FindReplace(auth_key, "Bearer", ""); Strings::Trim(auth_key); LogHTTPDetail( "Request Authorization key is [{}] set key is [{}] match [{}]", auth_key, authorization_key, auth_key == authorization_key ? "true" : "false" ); // authorization key matches, pass the request on to the route handler if (!authorization_key.empty() && auth_key != authorization_key) { LogHTTPDetail("[Sidecar] Returning as unhandled, authorization passed"); return httplib::Server::HandlerResponse::Unhandled; } } } if (!authorization_key.empty()) { nlohmann::json j; j["error"] = "Authorization key not valid!"; res.set_content(j.dump(), "application/json"); res.status = HTTP_RESPONSE_UNAUTHORIZED; return httplib::Server::HandlerResponse::Handled; } return httplib::Server::HandlerResponse::Unhandled; } ); api.Get("/api/v1/test-controller", SidecarApi::TestController); api.Get("/api/v1/loot-simulate", SidecarApi::LootSimulatorController); LogInfo("Webserver API now listening on port [{0}]", web_api_port); // this is not supposed to bind to the outside world api.listen("localhost", web_api_port); }