一、项目模块设计思路
目的:实现HTTP服务器搭建
思想:设计请求路由表,记录请求方法与对应业务的处理函数映射关系。用户实现请求方法和处理函数添加到路由表,服务器只接受请求并调用用户的处理函数即可。
处理流程:
二、成员变量
定义请求处理函数,作用是给我请求对象,我处理后返回应答对象
using Handler = function<void(const HttpRequest &, HttpResponse *)>;
using Handlers = vector<std::pair<regex, Handler>>; // 匹配的是资源路径的正则表达式来对应处理函数
定义四个请求方法对应的请求处理函数的路由表
Handlers _get_route;
Handlers _post_route;
Handlers _put_route;
Handlers _delete_route;
定义高并发服务器:TcpServer _server;
静态资源的相对根目录:string _basedir;
三、成员函数
1、私有函数1:错误信息填充 void ErrorHandler(const HttpRequest &req, HttpResponse *rsp)
填充应答正文的 html 错误网络页面,并设置正文类型是 html
2、私有函数2:组织应答报文并发送 void WriteResponse(const PtrConnection &conn, const HttpRequest &req, const HttpResponse &rsp)
(1)完善应答报头:Connection, Context-Length, Context-Type, Location
(2)组织应答报文:应答行 + 应答报头 + 空行 + 应答正文
(3)发送
3、私有函数3:判断是否是静态资源请求 bool IsFileHandler(const HttpRequest &req)
(1)是否设置了静态资源根目录
(2)请求方法是否是 GET 或 HEAD
(3)资源路径是否合法
(4)要求资源路径必须存在并且是普通文件(如果请求目录后面加上 index.html 再判断是不是普通文件)
4、私有函数4:静态资源请求处理 void FIleHandler(const HttpRequest &req, HttpResponse *rsp)
(1)先把请求中的相对资源路径加上静态资源根目录,如果请求目录后面加上 index.html
(2)将绝对路径中的文件读入 rsp 的正文中
(3)设置正文的类型
5、私有函数5:功能性请求处理 void Dispatcher(const HttpRequest &req, HttpResponse *rsp, Handler &handlers)
循环遍历路由表里面的正则资源路径,如果匹配就执行对应的处理函数,找不到应答状态码404
6、私有函数6:总处理请求 void Route(HttpRequest &req, HttpResponse *rsp)
(1)如果是静态资源请求就调静态处理函数
(2)如果请求方法是 GET / HEAD 就用 _get_route
如果请求方法是 PUT 就用 _put_route
如果请求方法是 POST 就用 _post_route
如果请求方法是 DELETE 就用 _delete_route
(3)全都不是就应答状态码405
7、私有函数7:设置给 TcpServer 的连接建立回调函数 void OnConnected(const PtrConnection &conn)
连接建立立即设置一个空上下文
8、私有函数8:设置给 TcpServer 的处理缓冲区数据回调函数 void OnMessage(const PtrConnection &conn, Buffer *buf)
最重要,融合所有子模块的 HTTP 服务器处理流程
(1)循环处理缓冲区数据直到空
(2)获取连接中的上下文数据
(3)通过报文解析获得请求对象,并初始化应答对象
(4)若解析出错(应答状态码 >= 400)错误信息填充,组织应答发送,清空上下文和缓冲区,关闭连接
(5)报文没有接收完整,直接返回等待下一次接收
(6)业务处理,填写应答对象
(7)组织应答报文并发送
(8)清空上下文(应为是循环,所以一定要清空)
(9)短连接关闭
9、公有函数1:构造函数
传入端口号和超时连接销毁时间
(1)默认开启超时连接销毁
(2)绑定私有函数两个回调
10、公有函数2:设置静态资源相对根目录 void SetBasedir(const string &basedir)
赋值私有成员
11、公有函数3:外部添加4种路由表的正则资源路径和对应的处理函数
赋值私有成员
12、公有函数4:设置线程池数量 void SetThreadCount(int count)
赋值私有成员
13、公有函数5:开始服务器 void Listen()
TcpServer 启动