基于 libhv+Brigand 实现 HTTP 接口批量自动化注册

一、代码核心功能与设计思路

  详解基于libhv(轻量级 HTTP 框架)和Brigand(编译期元编程库)实现 HTTP 接口批量自动化注册的完整代码,核心目标是摆脱手动逐个注册接口的繁琐,通过模板元编程在编译期遍历接口列表,自动完成路由注册,同时保证类型安全和扩展性。

1. 核心技术栈

  • libhv:轻量级、高性能的 HTTP/WS/MQTT 框架,提供 HTTP 服务端 / 客户端核心能力;
  • Brigand:C++ 编译期元编程库,支持编译期遍历类型列表、拼接列表等操作;
  • C++11 及以上:模板 constexpr、枚举类、std::function 等特性。

二、代码逐模块详解

1. 基础类型定义(枚举 + 函数指针) 

// 1. HTTP方法枚举类(语义清晰,避免魔法值)
enum class HttpMethodType { GET, POST, PUT, DELETE };

// 2. 处理器函数指针
typedef int (*HANDLER_FP)(const HttpContextPtr&);
  • 关键说明:
    • 枚举类HttpMethodType替代字符串 / 整型,避免命名冲突和类型不安全;
    • 函数指针HANDLER_FP严格匹配 libhv 的http_ctx_handler签名(返回int,参数为HttpContextPtr)

2. 接口处理器模板(ApiHandler)

// 接口处理器模板:封装单个接口的路径、处理器函数、请求方法
template <const char* Path, HANDLER_FP HandlerFunc, HttpMethodType Method>
struct ApiHandler {
    static constexpr const char* path = Path;       // 接口路径(编译期常量)
    static constexpr HANDLER_FP handler = HandlerFunc; // 处理器函数指针
    static constexpr HttpMethodType method = Method; // HTTP请求方法
}; 
  • 设计目的:将单个接口的核心信息(路径、函数、方法)封装为模板类型,使接口成为 “编译期可遍历的类型”;
  • 关键特性:
    • 所有成员均为static constexpr,确保编译期确定值,无运行期开销;
    • 模板参数为非类型参数(路径常量、函数指针、枚举值),编译期绑定接口信息。

3. 业务处理器实现(AcousticHandler)

class AcousticHandler {
public:
    // GET接口:获取升级进度
    static int get_progress(const HttpContextPtr& ctx) {
        std::cout << "获取升级进度" << std::endl;
        return 200; // 返回HTTP状态码(libhv要求必须返回int)
    }
    // POST接口:更新进度
    static int update_progress(const HttpContextPtr& ctx)
    {
        std::cout << "更新" << std::endl;
        return 200;
    }
};
 
  • 核心要求:
    • 函数必须为static(匹配函数指针类型,无需实例化类);
    • 返回值为int(对应 HTTP 状态码,如 200 = 成功、404 = 未找到);
    • 参数为HttpContextPtr(libhv 的上下文对象,可获取请求 / 设置响应)。
     

4. 接口列表定义(编译期)

// 接口路径常量(constexpr确保编译期常量,避免链接器重定位警告)
constexpr const char dev_update_progress[] = "/progress";
constexpr const char dev_get_progress[] = "/get_progress";

// 定义单个接口的处理器类型
using get_pkg_progress_handler = ApiHandler<
    dev_get_progress,
    AcousticHandler::get_progress,
    HttpMethodType::GET
>;
using update_pkg_progress_handler = ApiHandler<
    dev_update_progress,
    AcousticHandler::update_progress,
    HttpMethodType::POST
>;

// 编译期接口列表(Brigand的list类型,支持编译期遍历)
using acoustic_handlers = brigand::list<update_pkg_progress_handler,get_pkg_progress_handler>;

 

5. 

struct RegHandler {
    hv::HttpService* router_p; // 指向libhv的HttpService实例

    // 构造函数:传入HttpService指针
    RegHandler(hv::HttpService* _router_p) : router_p(_router_p) {}

    // 模板运算符():处理单个ApiHandler类型的注册
    template <typename ApiHandlerT>
    void operator()(brigand::type_<ApiHandlerT>) {
        switch (ApiHandlerT::method) {
            case HttpMethodType::GET:
                router_p->GET(ApiHandlerT::path, ApiHandlerT::handler);
                std::cout << "注册 GET 接口成功: " << ApiHandlerT::path << std::endl;
                break;
            case HttpMethodType::POST:
                router_p->POST(ApiHandlerT::path, ApiHandlerT::handler);
                std::cout << "注册 POST 接口成功: " << ApiHandlerT::path << std::endl;
                break;
        }
    }
};

 

  • 设计思路:
    • 模板运算符()接收brigand::type_<ApiHandlerT>(Brigand 遍历类型的包装器);
    • 根据ApiHandlerT::method自动选择GET/POST方法注册,无需手动区分。

6. 路由类(Router)

// 模板Router类:继承libhv的HttpService,批量注册接口
template <typename HandlerList>
class Router : public hv::HttpService {
public:
    Router() {
        // 编译期遍历HandlerList,调用RegHandler注册每个接口
        brigand::for_each<HandlerList>(RegHandler(this));
    }
};
  • 核心逻辑:
    • 继承hv::HttpService,成为 libhv 可识别的路由服务;
    • 构造函数中通过brigand::for_each遍历编译期接口列表,自动注册所有接口;
    • 模板参数HandlerList为 Brigand 类型列表,支持灵活替换不同接口列表。

7. 主函数(启动服务器)

int main() {
    // 创建Router实例(自动注册acoustic_handlers中的所有接口)
    Router<acoustic_handlers> router;
    hv::HttpServer server;
    // 注册路由服务到HTTP服务器
    server.registerHttpService(&router);
    // 配置服务器端口和线程数
    server.setPort(8080);
    server.setThreadNum(4);
    std::cout << "Server running on http://localhost:8080" << std::endl;
    // 启动服务器
    server.run();
    return 0;
}
  • 关键步骤:
    • 实例化Router<acoustic_handlers>时,构造函数自动完成所有接口注册;
    • server.registerHttpService将路由服务绑定到 HTTP 服务器;
    • server.run()启动服务器,监听 8080 端口。

 

6. 完整代码

#include <hv/HttpService.h>
#include <hv/HttpServer.h>
#include <hv/HttpContext.h>
#include "brigand/brigand.hpp"
#include <iostream>
#include <functional>

enum class HttpMethodType { GET, POST, PUT, DELETE };
typedef int (*HANDLER_FP)(const HttpContextPtr&);


template <const char* Path, HANDLER_FP HandlerFunc, HttpMethodType Method>
struct ApiHandler {
    static constexpr const char* path = Path;
    static constexpr HANDLER_FP handler = HandlerFunc; // 声明
    static constexpr HttpMethodType method = Method;
};


class AcousticHandler {
public:
    static int get_progress(const HttpContextPtr& ctx) {
        std::cout << "获取升级进度" << std::endl;
        return 200;
    }
    static int update_progress(const HttpContextPtr& ctx)
    {
        std::cout << "更新" << std::endl;
        return 200;
    }
};


constexpr const char dev_update_progress[] = "/progress";
constexpr const char dev_get_progress[] = "/get_progress";

using get_pkg_progress_handler = ApiHandler<
    dev_get_progress,
    AcousticHandler::get_progress,
    HttpMethodType::GET
>;
using update_pkg_progress_handler = ApiHandler<
    dev_update_progress,
    AcousticHandler::update_progress,
    HttpMethodType::POST
>;


using acoustic_handlers = brigand::list<update_pkg_progress_handler,get_pkg_progress_handler>;

struct RegHandler {
    hv::HttpService* router_p;

    RegHandler(hv::HttpService* _router_p) : router_p(_router_p) {}

    template <typename ApiHandlerT>
    void operator()(brigand::type_<ApiHandlerT>) {
        switch (ApiHandlerT::method) {
            case HttpMethodType::GET:
                router_p->GET(ApiHandlerT::path, ApiHandlerT::handler);
                std::cout << "注册 GET 接口成功: " << ApiHandlerT::path << std::endl;
                break;
            case HttpMethodType::POST:
                router_p->POST(ApiHandlerT::path, ApiHandlerT::handler);
                std::cout << "注册 POST 接口成功: " << ApiHandlerT::path << std::endl;
                break;
            
        }
    }
};

// Router 类(批量注册)
template <typename HandlerList>
class Router : public hv::HttpService {
public:
    Router() {
        brigand::for_each<HandlerList>(RegHandler(this));
    }
};

// 主函数测试
int main() {
    Router<acoustic_handlers> router;
    hv::HttpServer server;
    server.registerHttpService(&router);
    server.setPort(8080);
    server.setThreadNum(4);
    std::cout << "Server running on http://localhost:8080" << std::endl;
    server.run();
    return 0;
}

运行测试

# 启动服务器
./http_server
# 输出:
# 注册 POST 接口成功: /progress
# 注册 GET 接口成功: /get_progress
# Server running on http://localhost:8080

# 测试GET接口(终端/Postman)
curl http://localhost:8080/get_progress
# 测试POST接口
curl -X POST http://localhost:8080/progress

 

posted @ 2026-03-12 20:50  潇潇O  阅读(1)  评论(0)    收藏  举报