首页 > 编程语言 >[C++] 简单解析http请求

[C++] 简单解析http请求

时间:2024-08-05 14:40:16浏览次数:13  
标签:std body http string C++ tokens vector 解析 size

#include <iostream>

#include <string>
#include <map>
#include <vector>
#include <regex>

class HttpRequest {
public:
    enum Method {
        GET,
        POST,
        UNKNOWN
    };

    enum Error {
        SUCCESS,
        FORMAT_ERROR,
        INCOMPLETE_REQUEST
    };

    HttpRequest() : method(Method::UNKNOWN) {}

    Error parse(const std::string& request) {

        std::vector<std::string> header_body = split(request, "\r\n\r\n");
        if (!header_body.size()) {
            return FORMAT_ERROR;
        }

        std::vector<std::string> lines = split(header_body[0], "\r\n");
        for (size_t i = 0; i < lines.size(); ++i) {
            if (i == 0) {
                std::vector<std::string> tokens = split(lines[i], " ");
                if (tokens.size() != 3) {
                    return FORMAT_ERROR;
                }
                if (tokens[0] == "GET") {
                    method = Method::GET;
                } else if (tokens[0] == "POST") {
                    method = Method::POST;
                    if (header_body.size() == 2) {
                        body = header_body[1];
                    }
                } else {
                    method = Method::UNKNOWN;
                }
                path = tokens[1];
                continue;
            }
            
            std::string & line = lines[i];
            if (line.find(":") != std::string::npos) {
                std::vector<std::string> kv = split(line, ": ");
                if (kv.size() != 2) {
                    return FORMAT_ERROR;
                }
                headers[kv[0]] = kv[1];
            }
        }

        if (method == Method::POST) {
            size_t content_length = std::strtold(headers["Content-Length"].c_str(), NULL);
            if (body.size() != content_length) {
                std::cout << body.size() << ":" << content_length << std::endl;
                return INCOMPLETE_REQUEST;
            }
        }
        return SUCCESS;
    }

    void dump() {
        std::cout << "method: " << method << std::endl;
        std::cout << "path: " << path << std::endl;
        std::cout << "headers: " << std::endl;
        for (auto & kv : headers) {
            std::cout << kv.first << ": " << kv.second << std::endl;
        }
        std::cout << "body: " << body << std::endl;
    }

private:
    Method method;
    std::string path;
    std::map<std::string, std::string> headers;
    std::string body;

    std::vector<std::string> split(const std::string &str, const std::string &delim) {
        std::vector<std::string> tokens;
        std::regex re(delim); // 创建正则表达式对象
        std::sregex_token_iterator it(str.begin(), str.end(), re, -1);
        std::sregex_token_iterator end;

        while (it != end) {
            tokens.push_back(*it++);
        }

        return tokens;
    }
};

int main() {
    std::string get_request = "GET /index.html HTTP/1.1\r\n"
                          "Host: www.example.com\r\n"
                          "User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36\r\n";

    HttpRequest req;
    req.parse(get_request);
    req.dump();

    std::string post_request = "POST /submit HTTP/1.1\r\n"
                            "Host: www.example.com\r\n"
                            "Content-Type: application/x-www-form-urlencoded\r\n"
                            "Content-Length: 15\r\n"
                            "\r\n"
                            "name=John&age=30";

    std::string post_request2 = "POST / HTTP/1.1\r\n"
                                "Host: 127.0.0.1:8899\r\n"
                                "User-Agent: curl/7.81.0\r\n"
                                "Accept: */*\r\n"
                                "Content-Length: 18\r\n"
                                "Content-Type: application/x-www-form-urlencoded\r\n"
                                "\r\n"
                                "SELECT * FROM fff;";

    int ret = req.parse(post_request2);
    req.dump();
    if (ret != HttpRequest::SUCCESS) {
        std::cout << "parse error: " << ret << std::endl;
    }

    return 0;
}

仅实现简单的解析功能,并未考虑性能和http的完整支持。需要说明INCOMPLETE_REQUEST结果是为了解决tcp一次接收不到完整包的情况,可能需要多次解析

标签:std,body,http,string,C++,tokens,vector,解析,size
From: https://www.cnblogs.com/cjdty/p/18343168

相关文章

  • c++递归
    这是我发的第一篇讲解类型的文章主要是报的班那边讲到了个很有趣的东西到时候会给些案例本期直接把花絮挂在最后面_____________________________________________________________________________c++里有两种函数一种是可以看成数据的(这种定义函数的类型有longlong,......
  • 视频笔记软件JumpVideo技术解析一:Electron案例-调用VLC播放器
              大家好,我是TheGodOfKing,是最强考研学习神器,免费视频笔记应用JumpVideo,可以快速添加截图时间戳,支持所有笔记软件,学习效率MAX!的开发者之一,分享技术的目的是想找到更多志同道合的人,如果有大学生加入,我们还允许他把项目作为毕设(只有一个名额哟)群(689978959),那么今......
  • c++中的sort
    前言Hello,大家好啊,我是文宇。正文sort函数是C++标准库提供的用于对数组或容器中的元素进行排序的函数。通过使用快速排序或其它高效的排序算法,sort函数能够以非常高效的方式对元素进行排序。sort函数用法灵活多样,可以对不同类型的元素进行排序,并且可以通过自定义比较函数或......
  • C++ 动态内存管理: `std::unique_ptr
    定义与头文件std::unique_ptr的功能定义于<memory>头文件中。它主要用于管理动态分配的内存,保证资源正确释放。函数模板std::make_unique非数组类型template<classT,class...Args>unique_ptr<T>make_unique(Args&&...args);C++14起用于构造非数组类......
  • C++递归找规律典型题:派蒙的问题
    题目描述:有一天,旅行者和派蒙来到了一个未知的世界。这个世界充满了奇幻的景色和令人迷失的迷宫。他们决定一起探索这个神秘的地方,希望寻找宝藏和解开谜题。当他们穿越迷宫的时候,他们突然来到了一个巨大的房间。房间的中央有一个巨大的石头柱子,上面镶嵌着奇怪的符号和图案,上面......
  • c++递归算法较难题:分解数字
    题目描述:输入自然数 n,然后将其分拆成由若干数相加的形式,参与加法运算的数可以重复,要求输出降序排列。输入描述:一个待拆分的自然数n,(n≤50) 。输出描述:若干个拆分的加法等式。样例输入:5样例输出:5=55=4+15=3+25=3+1+15=2+2+15=2+1+1+15=1+1+1+1+1题目思想:将要分......
  • C++回溯算法经典例题:四皇后问题
    问题简介:在一个4×4的棋盘上,任意两个皇后都不能处在同一行、同一列任意两个皇后都不能处在同一斜线上(主斜线、反斜线)。题目分析:1.假设第一个皇后在(1,1):    1)在x=3时会卡死            2)在x=4时会卡死        2.假设第一个皇后在(2,1): ......
  • 深入解析通信协议在网络中的神奇应用
    好久不见!又到了分享时间~通信协议是网络通信的基石,它们决定了数据在网络中的传输方式和处理规则。接下来,让我们一起看看通信协议在网络通信中的具体应用吧!1.互联网通信互联网通信是最广泛使用的应用场景之一。以下是一些常见的互联网通信协议及其应用。HTTP/HTTPS:用于浏览......
  • C++简单模拟:电梯问题
    问题描述:某城市最高建筑物只有一个电梯,一个请求列表是由 n 个正整数组成的。数字表示电梯将停在哪个楼层。电梯向上移动一层需要 6 秒,向下移动一层需要 4 秒。电梯每次停下会停留 5 秒,对于给定的请求列表,需要计算用于满足列表中所有请求的总时间。电梯开始时在第一层......
  • C++商店管理系统
    代码中使用了C++11的特性后面有些输出(cout输出的)的提示文本是英文,因为懒得敲中文源码在最后面文末投票参与一下谢谢商品数据保存在items.txt用户数据保存在users.txt实现功能1.添加商品(商品ID,商品名,库存数量,价格)填写完信息后询问是否执行2.修改商品(先提示原有信......