This repository has been archived by the owner on Sep 27, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
9 changed files
with
372 additions
and
261 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,84 +1,61 @@ | ||
// #pragma once | ||
// #include "API.h" | ||
// #include <functional> | ||
// #include <thread> | ||
|
||
|
||
// namespace pmc::backend { | ||
|
||
// This function defined in the header file. | ||
// void startServer() { | ||
// auto& cfg = pmc::config::cfg.network; | ||
|
||
// #ifdef DEBUG | ||
// std::cout << "[DBG] Config: " << std::endl; | ||
// std::cout << " Enable: " << cfg.enable << std::endl; | ||
// std::cout << " Listen IP: " << cfg.listenIP << std::endl; | ||
// std::cout << " Listen Port: " << cfg.listenPort << std::endl; | ||
// std::cout << " Allow CORS: " << cfg.allowCORS << std::endl; | ||
// std::cout << " Token: " << cfg.token << std::endl; | ||
// #endif | ||
|
||
// if (!cfg.enable) return; | ||
|
||
|
||
// clang-format off | ||
/* | ||
TODO: We need find a good and header-only's C++ Http library. | ||
The following libraries are excluded: | ||
cpp-httplib | ||
cinatra | ||
drogon | ||
*/ | ||
// clang-format on | ||
|
||
|
||
// Create server instance | ||
// auto& logger = pmc::entry::getInstance().getSelf().getLogger(); | ||
// drogon::app() | ||
// .setLogPath("./logs/PermissionCore/net") | ||
// .setLogLevel(trantor::Logger::LogLevel::kInfo) | ||
// .addListener(cfg.listenIP, cfg.listenPort) | ||
// .setThreadNum(4) | ||
// .enableRunAsDaemon(); | ||
|
||
|
||
// drogon::app().registerHandler( | ||
// "/pmc/validate", | ||
// [](const drogon::HttpRequestPtr& req, std::function<void(const drogon::HttpResponsePtr&)>&& callback) { | ||
// string token = req->getHeader("Authorization"); | ||
// pmc::entry::getInstance().getSelf().getLogger().warn("Validate token: ", token); | ||
// callback(drogon::HttpResponse::newHttpJsonResponse("hello world")); | ||
// }, | ||
// {drogon::Get} | ||
// ); | ||
|
||
|
||
// Set server routes | ||
// svr.set_http_handler<cinatra::GET>( | ||
// "/pmc/validate", | ||
// [](cinatra::request&, cinatra::response& res) { | ||
// res.set_status_and_content(cinatra::status_type::ok, "Hello, world!"); | ||
// }, | ||
// mCORS{}, | ||
// mLog{}, | ||
// mAuth{} | ||
// ); | ||
// svr.set_http_handler("/pmc/list/all/core", handler_ListCore); | ||
// svr.set_http_handler("/pmc/list/all/plugin", handler_ListPlugn)); | ||
// svr.set_http_handler("/pmc/list/all/perm", handler_ListPerm); | ||
|
||
|
||
// Start server | ||
// logger.info("Try Start server on {}:{}."_tr(cfg.listenIP, cfg.listenPort)); | ||
// std::thread([&svr]() { | ||
// auto err = svr.sync_start(); | ||
// pmc::entry::getInstance().getSelf().getLogger().error("Fail in \"sync_start\", code: ", | ||
// static_cast<int>(err)); | ||
// printf("Fail in \"sync_start\", code: %d\n", static_cast<int>(err)); | ||
// }).detach(); | ||
// svr.async_start(); | ||
// drogon::app().run(); | ||
// } | ||
|
||
// } // namespace pmc::backend | ||
#include "API.h" | ||
#include "fmt/compile.h" | ||
#include <filesystem> | ||
#include <fstream> | ||
#include <sstream> | ||
|
||
using string = std::string; | ||
using ll::i18n_literals::operator""_tr; | ||
using json = nlohmann::json; | ||
namespace fs = std::filesystem; | ||
|
||
|
||
// 全局定义 HttpService 实例, 保证其生命周期与程序一致 | ||
hv::HttpService router; | ||
hv::HttpServer svr; | ||
|
||
|
||
namespace pmc::backend { | ||
|
||
|
||
void startAPIServerThread() { | ||
auto& cfg = pmc::config::cfg.Network; | ||
auto& logger = pmc::entry::getInstance().getSelf().getLogger(); | ||
if (!cfg.Enable) return; | ||
|
||
// 注册路由 | ||
router.GET("/api/validate", [cfg](HttpRequest* req, HttpResponse* res) { CheckToken_RS(req, res, cfg); }); | ||
|
||
// Query => plugin/perm | ||
router.GET("/api/query/{type}", [cfg](const HttpContextPtr& ctx) { | ||
CheckToken_CTX(ctx, cfg); | ||
string type = ctx->param("type"); | ||
hv::Json res; | ||
res["type"] = type; | ||
|
||
// 查询指定类型数据 | ||
if (type == "plugin") { | ||
res["data"] = pmc::PermissionManager::getInstance().getAllKeys(); | ||
} else if (type == "perm") { | ||
|
||
} else { | ||
res["status"] = 400; | ||
res["message"] = "Bad Request"; | ||
} | ||
// 发送响应 | ||
return ctx->sendJson(res); | ||
}); | ||
|
||
|
||
// 启动 HTTP 服务器 | ||
svr.port = cfg.Port; | ||
svr.service = &router; | ||
svr.setThreadNum(4); // 分配4个线程处理请求 | ||
svr.start(); | ||
logger.info("Start api server on 127.0.0.1:{0}."_tr(cfg.Port)); | ||
if (cfg.Token == "default_token") { | ||
logger.warn("Token is not set, please set it in config.toml."_tr()); | ||
} | ||
} | ||
|
||
} // namespace pmc::backend |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,68 +1,53 @@ | ||
// #pragma once | ||
// #include "ll/api/Logger.h" | ||
// #include "nlohmann/json.hpp" | ||
// #include "string" | ||
// #include <ll/api/i18n/I18n.h> | ||
// #include <stdexcept> | ||
// #include <thread> | ||
|
||
|
||
// #include "Config/Config.h" | ||
// #include "Entry/Entry.h" | ||
// #include "PermissionCore/Group.h" | ||
// #include "PermissionCore/PermissionCore.h" | ||
// #include "PermissionCore/PermissionManager.h" | ||
// #include "PermissionCore/PermissionRegister.h" | ||
// #include "ServerLog.h" | ||
|
||
|
||
// namespace pmc::backend { | ||
|
||
// using string = std::string; | ||
// using ll::i18n_literals::operator""_tr; | ||
// using json = nlohmann::json; | ||
|
||
// void startServer(); | ||
|
||
// using fn = std::function<void(const httplib::Request&, httplib::Response&)>; | ||
|
||
// #ifdef DEBUG | ||
// #define DebugPrintRequest(req) \ | ||
// pmc::entry::getInstance().getSelf().getLogger().warn( \ | ||
// "[Request]: ", \ | ||
// ServerManager::getInstance().headersToString(req.headers) \ | ||
// ); | ||
// #else | ||
// #define DebugPrintRequest(req) ; | ||
// #endif | ||
|
||
|
||
// #define AutoHandler(fn) \ | ||
// [](const httplib::Request& _req, httplib::Response& _res) { \ | ||
// DebugPrintRequest(_req); \ | ||
// pmc::entry::getInstance().getSelf().getLogger().warn("[" + _req.method + "] " + _req.path); \ | ||
// auto& _manager = ServerManager::getInstance(); \ | ||
// const string _reqTime = _manager.getCurrentTimeString(); \ | ||
// try { \ | ||
// auto _token = _req.get_header_value("Authorization"); \ | ||
// if (_token.empty()) { \ | ||
// _res.status = httplib::StatusCode::Unauthorized_401; \ | ||
// _manager.writeHttpRequestLog(_req, _res, _reqTime); \ | ||
// return; \ | ||
// } \ | ||
// if (_token != pmc::config::cfg.network.token) { \ | ||
// _res.status = httplib::StatusCode::Forbidden_403; \ | ||
// _manager.writeHttpRequestLog(_req, _res, _reqTime); \ | ||
// return; \ | ||
// } \ | ||
// fn(_req, _res); \ | ||
// _manager.writeHttpRequestLog(_req, _res, _reqTime); \ | ||
// } catch (...) { \ | ||
// _res.status = httplib::StatusCode::InternalServerError_500; \ | ||
// _manager.writeHttpRequestLog(_req, _res, _reqTime); \ | ||
// throw; \ | ||
// } \ | ||
// } | ||
|
||
|
||
// } // namespace pmc::backend | ||
#pragma once | ||
#include "APILogger.h" | ||
#include "Config/Config.h" | ||
#include "Date.h" | ||
#include "Entry/Entry.h" | ||
#include "PermissionCore/Group.h" | ||
#include "PermissionCore/PermissionCore.h" | ||
#include "PermissionCore/PermissionManager.h" | ||
#include "PermissionCore/PermissionRegister.h" | ||
#include "hv/HttpContext.h" | ||
#include "hv/HttpMessage.h" | ||
#include "hv/HttpServer.h" | ||
#include "hv/HttpService.h" | ||
#include "hv/http_content.h" | ||
#include "hv/httpdef.h" | ||
#include "ll/api/Logger.h" | ||
#include "nlohmann/json.hpp" | ||
#include "string" | ||
#include <filesystem> | ||
#include <functional> | ||
#include <ll/api/i18n/I18n.h> | ||
#include <memory> | ||
#include <stdexcept> | ||
#include <thread> | ||
|
||
|
||
namespace pmc::backend { | ||
|
||
void startAPIServerThread(); | ||
|
||
#define CheckToken_RS(req, res, cfg) \ | ||
APILogger::log(req); \ | ||
if (req->GetHeader("Authorization") != "Bearer " + cfg.Token) { \ | ||
res->json["status"] = 401; \ | ||
res->json["message"] = "Unauthorized"; \ | ||
return 401; \ | ||
} \ | ||
res->json["status"] = 200; \ | ||
res->json["message"] = "OK"; \ | ||
return 200; | ||
|
||
#define CheckToken_CTX(ctx, cfg) \ | ||
APILogger::log(ctx); \ | ||
string _token = ctx->header("Authorization"); \ | ||
if (_token != "Bearer " + cfg.Token) { \ | ||
ctx->setStatus(http_status::HTTP_STATUS_UNAUTHORIZED); \ | ||
hv::Json _tres; \ | ||
_tres["status"] = 401; \ | ||
_tres["message"] = "Unauthorized"; \ | ||
return ctx->sendJson(_tres); \ | ||
} | ||
|
||
} // namespace pmc::backend |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
#include "APILogger.h" | ||
#include "Date.h" | ||
#include "Entry/Entry.h" | ||
#include <filesystem> | ||
#include <ll/api/i18n/I18n.h> | ||
|
||
|
||
namespace pmc::backend { | ||
|
||
void APILogger::checkAndUpdateCurrTime() { | ||
auto now = utils::Date::now(); | ||
mCurrTime = fmt::format( | ||
"{}-{}-{}", | ||
std::to_string(now.getYear()), | ||
std::to_string(now.getMonth()), | ||
std::to_string(now.getDay()) | ||
); | ||
} | ||
|
||
fs::path APILogger::getAndCreateLogDir() { | ||
auto path = fs::current_path() / "logs" / "PermissionCore"; | ||
if (!fs::exists(path)) { | ||
fs::create_directories(path); | ||
} | ||
return path; | ||
} | ||
|
||
|
||
using ll::i18n_literals::operator""_tr; | ||
void APILogger::openFile() { | ||
checkAndUpdateCurrTime(); | ||
auto path = getAndCreateLogDir() / ("Api-" + mCurrTime + ".csv"); | ||
if (!fs::exists(path)) { | ||
fs::create_directories(path.parent_path()); | ||
} | ||
mOpenedFile.open(path, std::ios::app); | ||
if (!mOpenedFile.is_open()) { | ||
entry::getInstance().getSelf().getLogger().error("Failed to open log file."_tr()); | ||
return; | ||
} | ||
mOpenedFile << "time,ip,method,url,token" << std::endl; | ||
} | ||
|
||
void APILogger::checkFile() { | ||
// 初次运行,创建并打开日志文件 | ||
if (!mOpenedFile.is_open()) { | ||
openFile(); | ||
} | ||
// 日志文件过期,创建并打开新的日志文件 | ||
auto now = utils::Date::now(); | ||
string fNow = fmt::format("{}-{}-{}", now.getYear(), now.getMonth(), now.getDay()); | ||
if (fNow == mCurrTime) return; | ||
mOpenedFile.close(); | ||
openFile(); | ||
} | ||
|
||
void APILogger::writeLine(const string& line) { | ||
checkFile(); | ||
mOpenedFile << line << std::endl; | ||
} | ||
|
||
APILogger& APILogger::getInstance() { | ||
static APILogger instance; | ||
return instance; | ||
} | ||
|
||
void APILogger::log(const HttpContextPtr& ctx) { | ||
std::ostringstream oss; | ||
oss << utils::Date{}.toString() << ","; // 请求时间 | ||
oss << ctx->ip() << ","; // 来源IP | ||
oss << ctx->method() << ","; // 请求方法 | ||
oss << ctx->url() << ","; // 请求路径 | ||
oss << ctx->header("Authorization") << ","; // 请求Token | ||
APILogger::getInstance().writeLine(oss.str()); | ||
} | ||
|
||
void APILogger::log(HttpRequest* req) { | ||
std::ostringstream oss; | ||
oss << utils::Date{}.toString() << ","; // 请求时间 | ||
oss << req->host << ","; // 来源IP | ||
oss << req->method << ","; // 请求方法 | ||
oss << req->url << ","; // 请求路径 | ||
oss << req->GetHeader("Authorization") << ","; // 请求Token | ||
APILogger::getInstance().writeLine(oss.str()); | ||
} | ||
|
||
} // namespace pmc::backend |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
#include "hv/HttpContext.h" | ||
#include "hv/HttpMessage.h" | ||
#include <filesystem> | ||
#include <fstream> | ||
#include <string> | ||
|
||
|
||
using string = std::string; | ||
namespace fs = std::filesystem; | ||
|
||
namespace pmc::backend { | ||
|
||
class APILogger { | ||
private: | ||
string mCurrTime; | ||
std::ofstream mOpenedFile; | ||
|
||
void checkAndUpdateCurrTime(); | ||
|
||
fs::path getAndCreateLogDir(); | ||
|
||
void openFile(); | ||
|
||
public: | ||
void checkFile(); | ||
|
||
void writeLine(const string& line); | ||
|
||
static APILogger& getInstance(); | ||
|
||
static void log(HttpRequest* req); | ||
static void log(const HttpContextPtr& ctx); | ||
}; | ||
|
||
} // namespace pmc::backend |
Oops, something went wrong.