oj_server.cpp模塊是整個在線oj項目與外界溝通的橋樑,負責項目後臺與外界的通信。在這個模塊中使用了github上一個http開源庫(上一篇博客我提到過),模板填充技術以及Json數據格式,裏面有些可能看不懂,後面的博客我會詳細介紹。
Server:httplib中的一個Server類
Get:Server中的Get請求方法
Post:Server中的Post方法
set_content:httplib中定義的響應接口
listen:Server中的監聽方法
//有興趣可以自己看源代碼
Server &Get(const char *pattern, Handler handler);
Server &Post(const char *pattern, Handler handler);
using Handler = std::function<void(const Request &, Response &)>;
void set_content(std::string s, const char *content_type);
bool listen(const char *host, int port, int socket_flags = 0);
OjModel:試題信息模塊的一個類,裏面封裝了獲取試題信息的方法
OjView:頁面渲染模塊,裏面封裝了用於將獲取到的信息渲染到網頁的方法
LOG:日誌模塊下一個打印消息的方法
Compiler:編譯模塊中的一個類
主頁面效果,很low
#include "httplib.h"
#include "oj_model.hpp"
#include "oj_view.hpp"
#include "oj_log.hpp"
#include "compile.hpp"
int main()
{
//httplib的時候,需要使用httplib使用的命名空間
using namespace httplib;
Server svr;
OjModel oj_model;
//獲取試題信息,信息來源於文件
svr.Get("/all_questions", [&oj_model](const Request& req, Response& resp){
std::vector<Question> ques;
oj_model.GetAllQuestions(&ques);
std::string html;
//想使用模板技術去填充html頁面
OjView::ExpandAllQuestionsHtml(&html, ques);
resp.set_content(html, "text/html; charset=UTF-8");
});
//正則表達式
// \b 單詞的分界
// *:匹配任意字符串
// \d:匹配一個數字
// (): 分組應用
// 源碼轉義:特殊字符按照特殊字符字面源碼編譯 R"(str)“
svr.Get(R"(/question/(\d+))", [&oj_model](const Request& req, Response& resp){
//1.去試題模塊查找對應題號的具體題目信息
// map當中(序號 名稱 題目地址 難度)
std::string desc;
std::string header;
//從querystr中獲取id
LOG(INFO, "req.matches") << req.matches[0] << ":" << req.matches[1] << std::endl;
// 2. 在題目地址的路徑下去加載單個題目的描述信息
struct Question ques;
oj_model.GetOneQuestion(req.matches[1].str(), &desc, &header, &ques);
//3.組織,返回給瀏覽器
std::string html;
OjView::ExpandOneQuestion(ques, desc, header, &html);
resp.set_content(html, "text/html; charset=UTF-8");
});
svr.Post(R"(/question/(\d+))", [&oj_model](const Request& req, Response& resp){
//1.從正文當中提取出來提交的內容,主要是提取code字段的內容
// 提交的內容當中有url編碼,需要對提交內容解碼
std::unordered_map<std::string, std::string> pram;
UrlUtil::PraseBody(req.body, &pram);
// 2. 編譯&&運行
std::string code;
oj_model.SplitingCode(pram["code"], req.matches[1].str(), &code);
Json::Value req_json;
req_json["code"] = code;
Json::Value resp_json;
Compiler::CompilerAndRun(req_json, &resp_json);
// 3.構造響應,json
const std::string errorno = resp_json["errorno"].asString();
const std::string reason = resp_json["reason"].asString();
const std::string stdout_reason = resp_json["stdout"].asString();
std::string html;
OjView::ExpandReason(errorno, reason, stdout_reason, &html);
resp.set_content(html, "text/html; charset=UTF-8");
});
LOG(INFO, "Listen in 0.0.0.0:20000");
LOG(INFO, "Server ready");
svr.listen("0.0.0.0", 20000);
return 0;
}