• 基于CppHttpLib的Httpserver


    1 背景

      大多数嵌入式设备由于没有屏幕输出,只能通过Web页面来配置。这里利用CPPHttpLib来实现HttpServer。

    2 HttpServer

    HttpServer是利用CPPHttpLib开源库实现的Http服务器CppHttpLib是基于C++11的HTTP开源库,开源协议是MIT.
    CppHttpLib下载地址

    2.1 HttpServer定义

    2.1.1 Http头文件

    #ifndef HTTP_H
    #define HTTP_H
    #include "httplib.h"
    namespace http = httplib;
    #endif
    
    • 1
    • 2
    • 3
    • 4
    • 5

    该文件引用C++ HTTPLIB库头文件httplib.h,将命名空间httplib重命名为http,简化后续引用。

    2.1.1 HttpServer头文件

    #include "http.h"
    
    #include 
    
    struct HttpServer : private http::Server
    {
        HttpServer(bool is_log = false);
    
        bool set_root_path(std::string const& url, std::string const& dir);
    
        HttpServer &get(const std::string &pattern, http::Server::Handler handler);
        HttpServer &post(const std::string &pattern, http::Server::Handler handler);
        HttpServer &put(const std::string &pattern, http::Server::Handler handler);
    
        bool run(const char *host, int port);
    private:
        std::string log(const http::Request &req, const http::Response &res);
        std::string dump_headers(const http::Headers &headers);
    private:
        bool is_log_;
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    类型说明:

    • HttpServer 构造函数,参数is_log用来指示HttpServer是否打印日志,在调试时会很有用。
    • set_root_path 设置静态网页的URL和文件路径
    • get 设置get请求处理函数
    • post 设置post请求处理函数
    • put 设置put请求处理函数
    • run 运行httpserver,参数host为主机地址,port为端口。

    2.2 HttpServer实现

    2.2.1 构造函数

    HttpServer::HttpServer(bool is_log)
    : is_log_(is_log)
    {
        if(is_log_)
          set_logger([this](const http::Request &req, const http::Response &res) 
          {
            printf("%s", this->log(req, res).c_str());
          });
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    函数说明:

    • 如果需要log,则调用HttpLib库的set_logger函数设置打印log函数。

    2.2.2 set_root_path

    bool HttpServer::set_root_path(std::string const& url, std::string const& dir)
    {
        return set_mount_point(url, dir);
    }
    
    • 1
    • 2
    • 3
    • 4

    函数说明:

    • 调用HttpLib库的set_mount_point设置静态网页的URL和文件路径

    2.2.3 get/post/put

    HttpServer &HttpServer::get(const std::string &pattern, http::Server::Handler handler)
    {
        Get(pattern, handler);
        return *this;
    }
    
    HttpServer &HttpServer::post(const std::string &pattern, http::Server::Handler handler)
    {
        Post(pattern, handler);
        return *this;
    }
    HttpServer &HttpServer::put(const std::string &pattern, http::Server::Handler handler)
    {
        Put(pattern, handler);
        return *this;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    函数说明:

    • 调用HttpLib库对象函数设置请求处理函数。
    • 函数返回HttpServer引用是为了连续设置请求函数。

    2.2.4 run

    bool HttpServer::run(const char *host, int port)
    {
        return listen(host, port);
    }
    
    • 1
    • 2
    • 3
    • 4

    函数说明:

    • 调用listen启动http服务,该函数是阻塞函数。如果不想要阻塞的话,可以放到线程中执行该函数。

    2.2.5 log

    std::string HttpServer::log(const http::Request &req, const http::Response &res)
    {
        std::string s;
        char buf[BUFSIZ];
    
        s += "================================\n";
    
        snprintf(buf, sizeof(buf), "%s %s %s", req.method.c_str(),
                req.version.c_str(), req.path.c_str());
        s += buf;
    
        std::string query;
        for (auto it = req.params.begin(); it != req.params.end(); ++it) {
            const auto &x = *it;
            snprintf(buf, sizeof(buf), "%c%s=%s",
                    (it == req.params.begin()) ? '?' : '&', x.first.c_str(),
                    x.second.c_str());
            query += buf;
        }
        snprintf(buf, sizeof(buf), "%s\n", query.c_str());
        s += buf;
    
        s += dump_headers(req.headers);
    
        s += "--------------------------------\n";
    
        snprintf(buf, sizeof(buf), "%d %s\n", res.status, res.version.c_str());
        s += buf;
        s += dump_headers(res.headers);
        s += "\n";
    
        if (!req.body.empty()) { s += req.body; }
    
        s += "\n";
    
      return s;
    }
    
    std::string HttpServer::dump_headers(const http::Headers &headers) {
      std::string s;
      char buf[BUFSIZ];
    
      for (auto it = headers.begin(); it != headers.end(); ++it) {
        const auto &x = *it;
        snprintf(buf, sizeof(buf), "%s: %s\n", x.first.c_str(), x.second.c_str());
        s += buf;
      }
    
      return s;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50

    函数说明:

    • log函数将Request和Response转换为文本方便后续输出。
    • dump_headers函数将Headers转换为文本。

    3 实例

    #include "httpserver.h"
    
    int main(int argc, char* argv[]) 
    {
        bool isLog = true;
        HttpServer server(isLog);
    
        if(argc > 1)
            server.set_root_path("/", argv[1]);
        else
            server.set_root_path("/", "dist/www");
        
        server.run("0.0.0.0", 80);
    
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    说明:

    • 定义HttpServer
    • 设置主页路径
    • 启动服务

    4 总结

    利用CppHttpLib库实现一个HttpServer还是很简单的。

  • 相关阅读:
    【云原生】Kubernetes----轻量级的现代HTTP反向代理和负载均衡器之Traefik
    详细讲解Linux内存泄漏检测实现原理与实现
    GTest从入门到入门
    硬盘对拷(硬盘复制)操作指南
    建造者模式和模板设计模式应该怎么使用
    【笔记】结合P02项目——maven继承与聚合
    DNSlog快速注入
    关于安卓编译报错(一)kotlin依赖报错
    Kotlin 协程 (5/6篇) - 响应式编程 Flow
    requests爬虫IP连接初始化问题及解决方案
  • 原文地址:https://blog.csdn.net/flysnow010/article/details/138013690