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也就设计完了。这个模块主要还是用于保存请求中的要素,所以他的设计十分简单。

相关推荐
zmjjdank1ng6 分钟前
OSI模型和TCP/IP模型
服务器·网络·tcp/ip
菜菜艾7 小时前
基于llama.cpp部署私有大模型
linux·运维·服务器·人工智能·ai·云计算·ai编程
重生的黑客7 小时前
Linux开发工具:条件编译、动静态库与 make/makefile 入门
linux·运维·服务器
minji...8 小时前
Linux 线程同步与互斥(三) 生产者消费者模型,基于阻塞队列的生产者消费者模型的代码实现
linux·运维·服务器·开发语言·网络·c++·算法
w6100104668 小时前
cka-2026-ConfigMap
java·linux·cka·configmap
cc_yy_zh9 小时前
Win10 家庭版找不到Device Guard; 无法处理 VMware Workstation与Device Guard不兼容问题
linux·vmware
航Hang*9 小时前
VMware vSphere 云平台运维与管理基础——第2章(扩展):VMware ESXi 5.5 安装、配置与运维
运维·服务器·github·系统安全·虚拟化
嵌入式吴彦祖9 小时前
Luckfox Pico Ultra W WIFI
linux·嵌入式硬件
SPC的存折9 小时前
MySQL 8组复制完全指南
linux·运维·服务器·数据库·mysql
运维行者_9 小时前
OpManager MSP NetFlow Analyzer集成解决方案,应对多客户端网络流量监控挑战
大数据·运维·服务器·网络·数据库·自动化·运维开发