基于 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

浙公网安备 33010602011771号