HttpRequest模块 --- 存储http请求要素

目录

模块设计思想

模块代码实现


模块设计思想

HttpRequest模块是存储 Http请求要素的模块,同时他也需要提供接口用于外部进行设置要素。

那么Http请求中有哪些要素呢?

首先请求行中,有请求方法,url ,协议版本,而uel中又分为资源路径和参数,参数是kv的形式,所以我们需要使用一个map来保存

而头部字段中,都是一些kv格式的属性,我们也是使用一个map来保存

最后就是正文部分,正文部分是交给上层业务逻辑去处理的,我们只需要按照头部字段中的Content-Length提取出来就行了。

那么我们需要保存的就是 : 请求方法,资源路径,参数,协议版本,头部字段,正文 ,当然,由于可能会存在中间的处理过程,比如对请求行的解析,我们会使用正则表达式来进行,我们可以再存储一个 std::smatch 来保存正则提取出来的结果。

由于HttpRequest后续我们是交给 上下文模块来进行设置的,为了方便,我们就直接将成员设置为公有的了,便于直接访问。

同时,对于参数和头部字段,我们可以提供结构,用来插入kv形式的参数和头部字段,以及查询是否有某个参数或者头部字段。

再HttpRequest的头部字段中,有一个很重要的信息就是正文长度,我们可以提供一个接口用来获取正文长度。

最后再提供一个接口用于判断长短连接,长短连接后续我们会用到。

模块代码实现

按照上面的逻辑,我们的接口其实都很简单,所以我们也不一一讲解了。

复制代码
//保存http请求的各个要素
class HttpRequest   
{
public:
std::string _method; //请求方法
std::string _path;   //资源路径
std::unordered_map<std::string,std::string> _params;    //参数
std::string _version;   //协议版本
std::unordered_map<std::string,std::string> _headers;   //头部字段
std::string _body;      //正文
std::smatch _matches;   //请求行的正则匹配结果
uint64_t _length;       //正文长度

public:
    //添加参数
    void AddParam(const std::string& key , const std::string& val)
    {
        //如果已经存在该key,那么也直接更新
        _params[key] = val;
    }
    //判断是否有该参数
    bool HasParam(const std::string& key)const
    {
        auto it = _params.find(key);
        return it != _params.end();
    }
    //获取参数
    std::string GetParam(const std::string& key)const
    {
        auto it = _params.find(key);
        if(it == _params.end()) return "";  //返回空串
        return it->second;
    }
    //添加头部字段
    void AddHeader(const std::string& key , const std::string& val)
    {
        _headers[key]=val;
    }
    //判断是否有某个头部字段
    bool HasHeader(const std::string& key)const
    {
        auto it = _headers.find(key);
        return it != _headers.end();
    }
    //判断是不是短连接,如果是短连接那么返回一个响应之后就关闭连接了
    bool Close()const
    {
        //长短连接: Connection: close/keep-alive
        auto it = _headers.find("Connection");
        if(it == _headers.end() || it->second == "close") return true;
        return false;
    }
    //获取正文长度
    size_t ContentLength()const
    {
        auto it = _headers.find("Content-Length");
        if(it == _headers.end()) return 0;
        return std::stol(it->second);
    }
};

最后,我们会注意到,如果是长连接,那么意味着可能会收到第二个报文,那么我们需要将HttpRequest的内容先清空,再去解析第二个报文。(后续我们的HttpRequest是作为HttpContext的一部分的)。

所以我们再提供一个Reset接口用于重置内容。

复制代码
    void Reset()
    {
        _method.clear();
        _path.clear();
        _params.clear();
        _version.clear();
        _headers.clear();
        _body.clear();
        std::smatch tmp;
        _matches.swap(tmp); //由于smatch没有提供clear接口,所以我们使用swap来进行重置
        _body.clear();
    }

那么HttpRequest也就设计完了。这个模块主要还是用于保存请求中的要素,所以他的设计十分简单。

相关推荐
R_.L17 分钟前
Linux : 线程【同步与互斥】
linux
再睡一夏就好19 分钟前
从硬件角度理解“Linux下一切皆文件“,详解用户级缓冲区
linux·服务器·c语言·开发语言·学习笔记
zm2 小时前
TCP 粘包
服务器·网络·php
honey ball5 小时前
R & S的EMI接收机面板
linux·运维·网络
GBXLUO7 小时前
如何使用远程桌面控制电脑
服务器
柳如烟@7 小时前
在Rocky Linux 9.5上部署MongoDB 8.0.9:从安装到认证的完整指南
linux·运维·mongodb
搬码临时工8 小时前
电脑怎么远程访问服务器?4种常见的简单方法
运维·服务器·网络·异地访问
QQ2740287568 小时前
Kite AI 自动机器人部署教程
linux·运维·服务器·人工智能·机器人·web3
.小墨迹8 小时前
Apollo学习——planning模块(3)之planning_base
linux·开发语言·c++·学习·自动驾驶
影龙帝皖9 小时前
Linux服务之lvs+keepalived nginx+keepalived负载均衡实例解析
linux·nginx·lvs