add old lci module
This commit is contained in:
1 parent
38a6e815f0
commit
8499631091
171 files changed
+25562
No files matched your search
@@ -0,0 +1,287 @@
|
||||
#include <boost/beast.hpp>
|
||||
#include <boost/beast/http.hpp>
|
||||
#include <boost/asio.hpp>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <filesystem>
|
||||
#include <thread>
|
||||
#include <memory>
|
||||
#include <regex>
|
||||
|
||||
namespace beast = boost::beast;
|
||||
namespace http = beast::http;
|
||||
namespace net = boost::asio;
|
||||
using tcp = boost::asio::ip::tcp;
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
// 获取MIME类型
|
||||
std::string get_mime_type(const std::string& path) {
|
||||
if (path.ends_with(".html") || path.ends_with(".htm")) return "text/html";
|
||||
if (path.ends_with(".css")) return "text/css";
|
||||
if (path.ends_with(".js")) return "application/javascript";
|
||||
if (path.ends_with(".json")) return "application/json";
|
||||
if (path.ends_with(".png")) return "image/png";
|
||||
if (path.ends_with(".jpg") || path.ends_with(".jpeg")) return "image/jpeg";
|
||||
if (path.ends_with(".gif")) return "image/gif";
|
||||
if (path.ends_with(".svg")) return "image/svg+xml";
|
||||
if (path.ends_with(".txt")) return "text/plain";
|
||||
if (path.ends_with(".ico")) return "image/x-icon";
|
||||
return "application/octet-stream";
|
||||
}
|
||||
|
||||
// 读取文件内容
|
||||
std::string read_file(const std::string& path) {
|
||||
std::ifstream file(path, std::ios::binary);
|
||||
if (!file.is_open()) {
|
||||
std::cerr << "无法打开文件: " << path << std::endl;
|
||||
return "";
|
||||
}
|
||||
|
||||
std::stringstream buffer;
|
||||
buffer << file.rdbuf();
|
||||
return buffer.str();
|
||||
}
|
||||
|
||||
// 处理HTTP请求
|
||||
class http_connection : public std::enable_shared_from_this<http_connection> {
|
||||
public:
|
||||
http_connection(tcp::socket socket, const std::string& static_dir)
|
||||
: socket_(std::move(socket)), static_dir_(static_dir) {}
|
||||
|
||||
void start() {
|
||||
read_request();
|
||||
}
|
||||
|
||||
private:
|
||||
void read_request() {
|
||||
auto self = shared_from_this();
|
||||
|
||||
http::async_read(socket_, buffer_, request_,
|
||||
[self](beast::error_code ec, std::size_t bytes_transferred) {
|
||||
if (!ec) {
|
||||
self->process_request();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void process_request() {
|
||||
response_.version(request_.version());
|
||||
response_.keep_alive(false);
|
||||
|
||||
std::string target = std::string(request_.target());
|
||||
|
||||
// 防止路径遍历攻击
|
||||
if (target.find("..") != std::string::npos) {
|
||||
response_.result(http::status::forbidden);
|
||||
response_.set(http::field::content_type, "text/plain");
|
||||
response_.body() = "禁止访问";
|
||||
send_response();
|
||||
return;
|
||||
}
|
||||
|
||||
// 处理根路径
|
||||
if (target == "/" || target == "/index.html") {
|
||||
serve_file("dashun_index.html");
|
||||
return;
|
||||
}
|
||||
|
||||
// 处理健康检查
|
||||
if (target == "/health") {
|
||||
response_.result(http::status::ok);
|
||||
response_.set(http::field::content_type, "text/plain");
|
||||
response_.body() = "大顺脚本前端服务运行正常";
|
||||
send_response();
|
||||
return;
|
||||
}
|
||||
|
||||
// 处理API请求
|
||||
if (target.starts_with("/api/")) {
|
||||
handle_api_request(target);
|
||||
return;
|
||||
}
|
||||
|
||||
// 处理静态文件
|
||||
serve_file(target.substr(1)); // 移除开头的'/'
|
||||
}
|
||||
|
||||
void handle_api_request(const std::string& target) {
|
||||
response_.result(http::status::ok);
|
||||
response_.set(http::field::content_type, "application/json");
|
||||
|
||||
if (target == "/api/status") {
|
||||
response_.body() = R"({
|
||||
"status": "running",
|
||||
"version": "1.0.0",
|
||||
"uptime": "0",
|
||||
"requests_served": 0
|
||||
})";
|
||||
} else if (target == "/api/info") {
|
||||
response_.body() = R"({
|
||||
"name": "大顺脚本前端服务",
|
||||
"description": "为pmc项目提供Web界面",
|
||||
"author": "大顺",
|
||||
"repository": "https://github.com/your-repo/pmc"
|
||||
})";
|
||||
} else {
|
||||
response_.result(http::status::not_found);
|
||||
response_.set(http::field::content_type, "application/json");
|
||||
response_.body() = R"({"error": "API endpoint not found"})";
|
||||
}
|
||||
|
||||
send_response();
|
||||
}
|
||||
|
||||
void serve_file(const std::string& filename) {
|
||||
std::string filepath = static_dir_ + "/" + filename;
|
||||
|
||||
// 安全检查:确保文件在静态目录内
|
||||
fs::path requested_path = fs::absolute(filepath);
|
||||
fs::path static_path = fs::absolute(static_dir_);
|
||||
|
||||
if (!fs::equivalent(requested_path.parent_path(), static_path) &&
|
||||
!requested_path.string().starts_with(static_path.string() + "/")) {
|
||||
response_.result(http::status::forbidden);
|
||||
response_.set(http::field::content_type, "text/plain");
|
||||
response_.body() = "禁止访问";
|
||||
send_response();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!fs::exists(filepath)) {
|
||||
response_.result(http::status::not_found);
|
||||
response_.set(http::field::content_type, "text/plain");
|
||||
response_.body() = "文件不存在: " + filename;
|
||||
send_response();
|
||||
return;
|
||||
}
|
||||
|
||||
std::string content = read_file(filepath);
|
||||
if (content.empty()) {
|
||||
response_.result(http::status::internal_server_error);
|
||||
response_.set(http::field::content_type, "text/plain");
|
||||
response_.body() = "读取文件失败";
|
||||
send_response();
|
||||
return;
|
||||
}
|
||||
|
||||
response_.result(http::status::ok);
|
||||
response_.set(http::field::content_type, get_mime_type(filename));
|
||||
response_.body() = content;
|
||||
send_response();
|
||||
}
|
||||
|
||||
void send_response() {
|
||||
auto self = shared_from_this();
|
||||
|
||||
response_.content_length(response_.body().size());
|
||||
|
||||
http::async_write(socket_, response_,
|
||||
[self](beast::error_code ec, std::size_t) {
|
||||
self->socket_.shutdown(tcp::socket::shutdown_send, ec);
|
||||
});
|
||||
}
|
||||
|
||||
tcp::socket socket_;
|
||||
beast::flat_buffer buffer_{8192};
|
||||
http::request<http::string_body> request_;
|
||||
http::response<http::string_body> response_;
|
||||
std::string static_dir_;
|
||||
};
|
||||
|
||||
// HTTP服务器
|
||||
class http_server {
|
||||
public:
|
||||
http_server(net::io_context& ioc, tcp::endpoint endpoint, const std::string& static_dir)
|
||||
: acceptor_(ioc), static_dir_(static_dir) {
|
||||
beast::error_code ec;
|
||||
|
||||
// 打开acceptor
|
||||
acceptor_.open(endpoint.protocol(), ec);
|
||||
if (ec) {
|
||||
throw beast::system_error{ec};
|
||||
}
|
||||
|
||||
// 设置地址重用
|
||||
acceptor_.set_option(net::socket_base::reuse_address(true), ec);
|
||||
if (ec) {
|
||||
throw beast::system_error{ec};
|
||||
}
|
||||
|
||||
// 绑定到端点
|
||||
acceptor_.bind(endpoint, ec);
|
||||
if (ec) {
|
||||
throw beast::system_error{ec};
|
||||
}
|
||||
|
||||
// 开始监听
|
||||
acceptor_.listen(net::socket_base::max_listen_connections, ec);
|
||||
if (ec) {
|
||||
throw beast::system_error{ec};
|
||||
}
|
||||
}
|
||||
|
||||
void start_accept() {
|
||||
acceptor_.async_accept(
|
||||
[this](beast::error_code ec, tcp::socket socket) {
|
||||
if (!ec) {
|
||||
std::make_shared<http_connection>(std::move(socket), static_dir_)->start();
|
||||
}
|
||||
start_accept();
|
||||
});
|
||||
}
|
||||
|
||||
private:
|
||||
tcp::acceptor acceptor_;
|
||||
std::string static_dir_;
|
||||
};
|
||||
|
||||
int main() {
|
||||
try {
|
||||
// 静态文件目录
|
||||
std::string static_dir = "static";
|
||||
|
||||
// 确保静态目录存在
|
||||
if (!fs::exists(static_dir)) {
|
||||
std::cerr << "警告: 静态目录 '" << static_dir << "' 不存在" << std::endl;
|
||||
if (!fs::create_directory(static_dir)) {
|
||||
std::cerr << "错误: 无法创建静态目录" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
// 检查主页文件是否存在
|
||||
std::string homepage = static_dir + "/dashun_index.html";
|
||||
if (!fs::exists(homepage)) {
|
||||
std::cerr << "警告: 主页文件 '" << homepage << "' 不存在" << std::endl;
|
||||
std::cerr << "请确保 dashun_index.html 文件在 static/ 目录中" << std::endl;
|
||||
}
|
||||
|
||||
// 创建IO上下文
|
||||
net::io_context ioc{1};
|
||||
|
||||
// 创建服务器端点(监听所有地址的8080端口)
|
||||
tcp::endpoint endpoint{tcp::v4(), 8080};
|
||||
|
||||
// 创建HTTP服务器
|
||||
http_server server{ioc, endpoint, static_dir};
|
||||
server.start_accept();
|
||||
|
||||
// 显示启动信息
|
||||
std::cout << "==========================================" << std::endl;
|
||||
std::cout << "大顺脚本前端服务已启动" << std::endl;
|
||||
std::cout << "监听地址: http://0.0.0.0:8080" << std::endl;
|
||||
std::cout << "静态文件目录: " << static_dir << std::endl;
|
||||
std::cout << "按 Ctrl+C 停止服务" << std::endl;
|
||||
std::cout << "==========================================" << std::endl;
|
||||
|
||||
ioc.run();
|
||||
|
||||
} catch (const std::exception& e) {
|
||||
std::cerr << "错误: " << e.what() << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
Reference in new issue
Block a user