Muduo网络库实现 [十四] - HttpResponse模块
目录
设计思路
类的设计
模块的实现
公有接口
疑问点
设计思路
这个模块和HttpRequest一样,主要就是存储http响应的要素,但是其实真正需要设置存储的要素会比http请求少,首先,要存储http的版本号,我们最终使用的是请求中的版本号。状态码描述不需要存储,而是后续再进行序列化的时候使用 StatuDesc 接口来获取。
我们来再看一下,响应报头的组成
所以再HttpResponse中真正需要存储的要素其实就只有响应行中的状态码,响应报头,响应正文,当然其实还需要额外存储一个东西就是重定向信息,因为未来可能对方请求的资源已经转移了,那么我们需要返回一个重定向报文,将新的url返回给客户端,所以我们还需要存储一个标记位用来表示是否重定向以及重定向的 url。
public:bool _statu; //重定义标识符std::string _body; //响应正文std::unordered_map<std::string,std::string> _headers; //响应报头std::string _redirect_flag; //重定向标志std::string _redirect_url;
};
类的设计
那么设计类就根据我们上面的要求去实现了,当HTTP服务器接收到一个客户端请求并处理后,在发送响应之前,先来添加必要的响应头信息。也就是上面蓝色部分的内容,这一部分是由上层的Http服务器模块来设置的,设置格式就是kv键。同样,Http协议要求报文肯定是要有头部字段的,如果没有那就说明这个报文是错误的。接着如果有头部字段,那就把头部字段的一些内容给获取出来。接着就是关于响应正文部分,也就是上面紫色的部分的内容,比如说请求的报文里是登录的内容,那么我们肯定是要给它返回一个登录的界面的,所以这个就是为什么要设置响应正文了。然后对content-type也要重点关注。对于一些请求资源的转移,我们也要让它能够重定向到新的url地址。然后我们还需要判断请求的报文是长连接还是短链接。最后就是把本次的数据给清除啦,不影响下次的响应
HttpResponse();// 清空类数据,防止影响下次获取void Reset();// 添加头部字段void SetHeader(const std::string &key, const std::string &val);// 是否有一个头部字段bool HasHeader(const std::string &key);// 获取头部字段std::string GetHeader(const std::string &key);// 设置响应正文void SetContent(const std::string &body, std::string &type);// 设置重定向信息void SetRedirect(const std::string &url, int status = 302);// 是否是长连接bool Close();};
模块的实现
公有接口
关于构造函数,我们要先设置默认值,初始化状态码 _status 为 200(表示 HTTP OK 状态) 。初始化重定向标志 _redirect_flag 为 false。
SetHeader函数将头部字段键值对插入到 _headers 映射容器中,提供一个简单的接口来设置 HTTP 响应头,如 Content-Type、Content-Length 等
HasHeader函数检查特定头部字段是否已经设置,用于条件判断和逻辑控制。在 _headers 中查找指定的 key 如果找到返回 true,否则返回 false
GetHeader函数获取指定头部字段的值,用于读取已设置的头部信息 在 _headers 中查找指定的 key。如果找到返回对应的值,否则返回空字符串
SetContent函数简化同时设置响应内容和内容类型的操作,确保两者匹配 。设置响应正文 _body
调用 SetHeader 设置 Content-Type
SetRedirect函数封装 HTTP 重定向的设置,使用标准的重定向状态码和目标 URL 。 设置状态码 _status(默认为 302 Found) ,设置重定向 URL _redirect_url ,标记重定向标志 _redirect_flag 为 true
Close()函数判断是否是长连接和短链接。 检查是否有 "Connection" 头部并且值是 "keep-alive"
如果是,返回 false(不关闭连接);否则返回 true(应该关闭连接)
ReSet()函数提供一个快速重置响应对象到初始状态的方法,便于对象复用
重置状态码为 200,重置重定向标志为 false,清空正文内容,清空所有头部字段,清空重定向 URL
public:HttpResponse():_status(200),_redirect_flag(false){}void SetHeader(const std::string &key, const std::string &val){_headers.insert({key,val});}bool HasHeader(const std::string &key){auto it = _headers.find(key);if(it == _headers.end()){return false;}return true;}std::string GetHeader(const std::string &key){auto it = _headers.find(key);if(it == _headers.end()){return "";}return it->second;}void SetContent(const std::string &body, std::string &type){_body = body;SetHeader}void SetRedirect(const std::string &url,int status = 302){_status = status;_redirect_url = url;_redirect_flag = true;}bool Close(){if(HasHeader("Connection") == true && GetHeader("Connection") == "keep-alive"){return false;}return true;}void ReSet(){_status = 200;_redirect_flag = false;_body.clear();_headers.clear();_redirect_url.clear();}
疑问点
为什么要在响应正文中设置报头的content-type,不能单独的去设置吗?
你也可以分开设置,但是一般都是放在一起的