C++网络编程实战项目--Sinetlib网络库(5)——HTTP服务器设计与实现
Sinetlib内嵌了一个简易的HTTP服务器,实现了url匹配和静态资源访问,可以使用作为RESTful API的后台。
整体架构
整体是建立在网络库连接的抽象上的,但服务器接收到消息,将其解析成HTTP Request,然后通过路由器进行匹配,得到匹配的Hander进行处理,如果没有匹配则直接返回404 Response。处理完生成对应的Response发送回去。
解析
对于http请求的解析,使用HttpParser,主要是使用有限状态机来进行字符串匹配。
路由
这里的设计参考了golang的mux包,首先Router下有多个Route,每个Route下又有多个Matcher。
每个Matcher都对应了一条匹配条件,比如要求请求的方法为GET。当一个请求匹配了Route下的所有条件,即匹配成功这个Route,就可以得到该Route的处理函数来处理Request了。如果没有匹配的Route,那么就使用默认的处理函数,即返回404页面。
Matcher的匹配主要是通过正则表达式来进行,用户可以利用正则表达式来取得一些参数,具体请参考github上的README. md
静态资源
文件的访问由File处理,它主要是提供该文件或目录的相关信息,并通过mmap内存映射方式将文件读取出来。
当用户访问资源时,相应的处理函数由FileHandler提供。
示例
#include "httpserver.h"
void OnHttpCallback(const HttpRequest& request, std::unordered_map<std::string, std::string>& match_map, HttpResponse* response)
{
response->SetStatusCode(HttpResponse::OK);
response->SetStatusMessage("OK");
response->SetContentType("text/html");
std::string body = "temp test page";
response->AddHeader("Content-Length", std::to_string(body.size()));
response->AppendHeaderToBuffer();
response->AppendBodyToBuffer(body);
}
int main()
{
Looper loop;
HttpServer s(&loop, 8888, 4);
s.NewRoute()
->SetPath("/path/{name:[a-zA-Z]+}")
->SetHeader("Connection", "keep-alive")
->SetHandler(OnHttpCallback);
s.NewRoute()
->SetPrefix("/file/")
->SetHandler(s.GetFileHandler("/home/"));
s.Start();
loop.Start();
}
使用上述程序,并通过浏览器访问,效果如下:
测试页面
静态资源