克隆仓库:git clone https://gitee.com/iqxg/cpp-httplib.git
1.下载高版本gcc:bash中输入以下命令
sudo yum -y install centos-release-scl
sudo yum -y install devtoolset-7-gcc devtoolset-7-gcc-c++ devtoolset-7-binutils
2.设置默认启动高版本gcc
打开文件
vim ~/.bash_profile
在最后添加:
scl enable devtoolset-7 bash
重启gcc
source ~/.bash_profile
yum install jsoncpp
yum install jsoncpp-devel
sudo yum install -y snappy-devel boost-devel zlib-devel.x86_64 python-pip
sudo pip install BeautifulSoup4
git clone https://gitee.com/HGtz2222/ThirdPartLibForCpp.git
cd ./ThirdPartLibForCpp/el7.x86_64/
sh install.sh
#include
#include
#include "httplib.h"
int main()
{
// 1.创建一个Server类对象
httplib::Server http_svr;
// 2.注册Get方法
http_svr.Get("/index", [](const httplib::Request& req, httplib::Response& resp){
std::cout << req.method << " " << req.path << " " << req.version << std::endl;
std::string html = "this is Linux~~";
resp.set_content(html, "text/html");
});
http_svr.listen("0.0.0.0", 17878);
return 0;
}
运行结果:打开浏览器输入IP:port
cpp-httplib源码分析:
我们只用到了:Get:获取资源,Post:传输实体主体
Get方法具体:
Server &Get(const char *pattern, Handler handler);
pattern:注册的回调函数资源路径,只有资源路径相同才会回调该函数
Handler:函数指针
Resquset:客户端的请求
Response:服务端的响应
题目存储:
对外提供接口:
oj_model.hpp:
struct Questions
{
std::string id_; // 题目id
std::string title_; // 题名
std::string comp_; // 题目难度
std::string path_; // 题目路径
std::string desc_; // 题目描述信息
std::string header_; // 预定义的头文件
std::string tail_; // 测试用例
};
// 从文件中加载数据到内存中,用unordereed_map组织数据
bool Load();
// 获取试题目录,出参用数组保存:vector
bool GetAllQuestions();
// 获取单个试题详细信息,出参自定义类型Questions
bool GetOneQues();
源码:
oj_view.hpp:
//根据所有的题目列表信息,生成HTML, 供网站首页显示
static void FillInAllQuestions(const std::vector<Question>& all_questions,std::string* html);
//根据指定的question, 生成HTML
static void FillInOneQuestion(const Question& question,std::string* html);
//根据运行结果或编译出错的结果,构造生成HTML
static void FillInResponse(const Json::Value& Resp, std::string* html);
源码:
oj_compile.hpp
// 编译并运行
static void CompileAndRun(Json::Value Req, Json::Value* Resp)
// 编译模块
static bool Compile(const std::string& filename)
// 运行模块
static int Run(const std::string& filename)
// 清理创建出来的文件
static void Clean(const std::string& filename)
源码:
#include
#include
#include
#include "httplib.h"
#include "oj_model.hpp"
#include "oj_view.hpp"
#include "oj_compile.hpp"
using namespace httplib;
int main()
{
Server svr;
OjModel model;
// 1.注册所有题目的资源路径
svr.Get("/all_questions", [&model](const Request &req, Response &resp){
std::vector<Questions> all_ques;
model.GetAllQuestions(&all_ques); // 获取所有题目信息
std::string html;
Oj_View::FillInAllQuestions(all_ques, &html); // 获取html页面
resp.set_content(html, "text/html"); // 设置响应体
});
// 2.注册单个题目的资源路径
svr.Get(R"(/question/(\d+))", [&model](const Request &req, Response &resp){
// 获取单个试题的信息
Questions question;
model.GetOneQues(req.matches[1], &question);
// 获取html页面
std::string html;
Oj_View::FillInOneQuestion(question, &html);
resp.set_content(html, "text/html");
});
// 3.注册提交代码并运行的路径
svr.Post(R"(/compile/(\d+))", [&model](const Request &req, Response &resp){
// 1.获取试题编号和内容
Questions question;
model.GetOneQues(req.matches[1], &question);
// 2.对浏览器的请求体进行切分,切分成key:value形式,再进行url解码
std::unordered_map<std::string, std::string> kv_map;
Urlcode::PraseBody(req.body, &kv_map);
//for (const auto it : kv_map)
//{
// std::cout << it.first << std::endl << it.second << std::endl;
//}
// 3.把code和预定义的头结合,创建出一个新的文件
std::string code = kv_map["code"];
std::string stdin = kv_map["stdin"];
Json::Value Req_Js;
Json::Value Resp_Js;
Req_Js["code"] = code + question.tail_;
Req_Js["stdin"] = stdin;
// 4.编译并运行用户提交的代码
Compiled::CompileAndRun(Req_Js, &Resp_Js);
// 5.根据不同的编译运行结果,返回响应
std::string html;
Oj_View::FillInResponse(Resp_Js, &html);
resp.set_content(html, "text/html");
});
// 设置逻辑根目录
svr.set_base_dir("./wwwroot");
// 打印日志信息
LOG(INFO, "listen_port") << ":18888" << std::endl;
svr.listen("0.0.0.0", 18888);
return 0;
}
源码:
static std::string WriteTmpFile(const std::string& code)
{
// 1.为了区分不同客户端发来的代码,我们应按时间生成不同的文件名
// 2.光按时间进行区分,不能保证线程安全,高并发情况下会出现问题
static std::atomic_uint id(0);
std::string filename = "tmp_" + std::to_string(TimeUtil::GetTimeStampMs()) + "." + std::to_string(id);
id++;
// 3.创建一个文件,并且把code写入文件
FileUtil::file_write(Compiled::SrcPath(filename), code);
return filename;
}