httplib::Server可快速搭建嵌入式RESTful路由:零依赖、单头文件、支持GET/POST/PUT/DELETE及路径参数(如/api/v1/sensor/:id),需手动处理OPTIONS预检、JSON解析容错、Content-Length设置与连接控制。

用 httplib::Server 快速搭出可运行的 RESTful 路由
嵌入式场景下,httplib(C++11 单头库)是极简可行的选择:无依赖、编译快、内存占用低。它不内置 REST 概念,但通过路径匹配 + HTTP 方法分发,能自然实现 CRUD 对应关系。
关键不是“造轮子”,而是把 GET/POST/PUT/DELETE 映射到具体函数——httplib::Server 的 .Get()、.Post() 等成员函数就是直接入口。
- 路由路径必须带前缀,比如
/api/v1/sensor,避免和静态资源路径冲突 - 路径参数用冒号声明:
/api/v1/sensor/:id,取值靠req.matches的std::smatch(注意索引从 1 开始) - 不要在回调里做阻塞操作(如文件读写、串口等待),否则整个服务器卡死;改用异步队列或状态机
解析 application/json 请求体时容易忽略的边界
嵌入式设备收到的 JSON 往往不规范:可能缺末尾换行、含 BOM、字段名大小写混用、数值溢出为 0 或 NaN。用 nlohmann::json 解析时,try-catch 不够,得主动校验结构。
-
req.body是std::string,但可能为空——先检查req.body.empty()再 parse - 用
json::parse(req.body, nullptr, false)启用宽松模式(跳过语法错误),再用.is_discarded()判断是否解析失败 - 访问字段前必须用
.contains("field")或.find("field") != j.end(),否则抛nlohmann::json::out_of_range - 整数字段建议用
j.at("value").get而非() j["value"].get,前者在缺失时抛异常,后者静默返回 0()
PUT 和 DELETE 在嵌入式中常被 Nginx 或浏览器预检拦住
很多嵌入式 Web 服务只测试了 GET/POST,上线后发现 App 发 PUT 失败——其实是浏览器发了 OPTIONS 预检请求,而服务器没响应。
- 必须显式注册
.Options("/api/.*", [](...){}),且响应头至少包含:Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS -
Access-Control-Allow-Origin设为*仅限调试;生产环境应限定为具体域名或白名单 IP - 某些旧版 MCU 的 TCP/IP 栈(如 lwIP)默认不处理
OPTIONS,需确认底层协议栈是否透传该方法 - 调试时用
curl -X OPTIONS -v http://ip/api/v1/sensor/123直接测,绕过浏览器缓存
返回 JSON 响应时控制 Content-Length 和连接复用
嵌入式 RAM 紧张,httplib 默认用 chunked encoding 回复,但部分老旧客户端(如某些 Modbus 网关的 HTTP 模块)只认 Content-Length。同时,HTTP/1.1 默认 keep-alive,但嵌入式常因 socket 资源少需主动关闭。
- 手动设置
res.set_content(json.dump(), "application/json");即可让httplib自动填Content-Length - 若需强制关闭连接,在响应后加
res.headers["Connection"] = "close"; - 避免在响应体里拼接字符串(如
"{ \"code\":" + std::to_string(code) + "}"),JSON 库生成更安全,也省去转义麻烦 - 大响应体(>4KB)考虑流式写入,但
httplib不支持;此时应拆成多次小接口,或改用write系统调用直写 socket
RESTful 在嵌入式里不是教条,而是约束——用标准方法名降低联调成本,但路径设计、错误码语义、负载格式必须贴合硬件实际能力。最常出问题的不是语法,是忘了 req.body 可能为空,或 json::parse 在内存不足时直接 abort。
大量免费API接口:立即使用
涵盖生活服务API、金融科技API、企业工商API、等相关的API接口服务。免费API接口可安全、合规地连接上下游,为数据API应用能力赋能!











