如果你在找一个 "不折腾" 的 C++ HTTP 库 ------ 不用搭复杂依赖、不用啃几千行文档,还能跨平台跑 HTTP 服务和客户端,那 cpp-httplib 大概率是你的菜。作为一个单头文件的轻量级库,它把 HTTP 客户端 / 服务器的核心功能封装得简洁又好用,尤其适合快速开发小型 Web 服务、API 调用工具,或是给 C++ 项目加个 HTTP 接口。这篇文章就从安装到实战,带你一步步把 cpp-httplib 用起来。
一、先搞懂:cpp-httplib 到底好在哪?
在开始写代码前,先聊聊它的核心优势 ------ 毕竟选库就像挑工具,得先知道它擅长啥:
-
真正的 "零依赖" :整个库就一个
httplib.h
头文件,不用装 Boost、不用配 curl,拷贝到项目里#include
就能用,对新手太友好了。 -
跨平台无压力:Windows(MinGW/MSVC)、Linux、macOS 都能跑,编译命令改改参数就行,不用为不同系统写两套代码。
-
同步 / 异步都支持:简单场景用同步调用(比如客户端发个请求等响应),高并发场景用异步操作,不用自己手撸线程池。
-
HTTP/1.1 特性拉满 :支持持久连接、管道化,还有文件上传必备的
multipart/form-data
,做个简单的文件服务器也没问题。 -
HTTPS/WSS 能搞定:虽然默认不带 SSL,但对接 OpenSSL 或 mbedTLS 后就能跑 HTTPS,编译时加个链接参数的事儿。
-
API 设计很直观 :比如服务器注册 GET 接口就用
Server::Get()
,客户端发 POST 请求就用Client::Post()
,看函数名就知道干啥的,不用查半天文档。
二、5 分钟搞定安装:就一行克隆命令
cpp-httplib 没有复杂的 "配置 - 编译 - 安装" 流程,直接从 GitHub 拉取源码就行,步骤就两步:
1. 克隆源码到本地
打开终端(Linux/macOS)或 Git Bash(Windows),执行以下命令,把源码拉到你的工作目录(比如~/workspace
):
git clone https://github.com/yhirose/cpp-httplib.git
拉完后,你会看到cpp-httplib
目录下有个httplib.h
------ 这就是整个库的核心,其他文件大多是示例和文档,不用管。
2. 项目中引用头文件
不用把库 "安装" 到系统目录,直接在你的 C++ 代码里指定头文件路径就行:
- 如果你把
cpp-httplib
目录和你的代码文件(比如main.cc
)放同级,引用方式是:
cpp
#include "cpp-httplib/httplib.h"
- 如果你只拷贝了
httplib.h
到代码目录,直接引:
cpp
#include "httplib.h"
三、核心类与接口:搞懂这 4 个就够了
cpp-httplib 的核心逻辑围绕 4 个关键结构 / 类展开:Request
(请求)、Response
(响应)、Server
(服务器)、Client
(客户端)。搞懂它们的成员和方法,基本就能应对 80% 的场景。
1. Request:解析客户端发来的请求
当客户端(比如浏览器)发请求到服务器时,cpp-httplib 会把请求信息封装成httplib::Request
对象,你可以从里面拿到这些关键信息:
成员 | 作用说明 | 示例 |
---|---|---|
method |
请求方法(GET/POST/PUT/DELETE 等) | req.method == "GET" |
path |
请求路径(比如/hi 、/user/123 ) |
req.path == "/hi" |
headers |
请求头(键值对,比如User-Agent ) |
req.headers["User-Agent"] |
params |
URL 参数(比如/search?name=test 里的name ) |
req.params["name"] |
body |
请求体(POST/PUT 请求的内容,比如表单数据) | req.body |
比如客户端发GET /search?keyword=cpp
,你就能通过req.path
拿到/search
,通过req.params["keyword"]
拿到cpp
。
2. Response:构造服务器要返回的响应
你需要通过httplib::Response
对象组装响应,核心方法和成员:
-
set_content(const std::string &content, const std::string &content_type)
:设置响应体内容和类型。比如返回 HTML 就用text/html
,返回 JSON 就用application/json
。 -
set_header(const std::string &key, const std::string &val)
:设置响应头,比如跨域需要的Access-Control-Allow-Origin: *
。 -
status
:HTTP 状态码(200 成功、404 找不到、500 服务器错误等)。
示例:返回一个 HTML 页面,状态码 200:
cpp
rsp.set_content("<h1>Hello from cpp-httplib</h1>", "text/html");
rsp.status = 200;
3. Server:搭建 HTTP 服务器
httplib::Server
是服务器的核心类,主要用来注册路由(比如 "访问/hi
时执行什么逻辑")和启动服务。
核心方法:注册请求处理器
服务器需要知道 "收到哪种请求、哪个路径时,执行什么代码",这就需要用这些方法:
-
Server::Get(const std::string &pattern, Handler handler)
:注册 GET 请求的处理器。 -
Server::Post(const std::string &pattern, Handler handler)
:注册 POST 请求的处理器。 -
同理还有
Put()
、Delete()
,对应 HTTP 的 PUT 和 DELETE 方法。
其中:
-
pattern
:路由匹配规则,比如/hi
(精确匹配)、/user/:id
(匹配/user/123
、/user/456
,:id
是参数)。 -
Handler
:处理函数,类型是std::function<void(const Request &, Response &)
------ 输入是请求,输出是响应。
启动服务:listen()
方法
注册完路由后,用listen(host, port)
启动服务器,比如监听所有网卡(0.0.0.0
)的 8080 端口:
cpp
if (_server.listen("0.0.0.0", 8080)) {
std::cout << "Server running on http://0.0.0.0:8080" << std::endl;
} else {
std::cerr << "Failed to start server" << std::endl;
}
4. Client:发送 HTTP 请求
如果你的 C++ 程序需要调用其他 HTTP 服务(比如调用接口获取数据),就用httplib::Client
。
构造 Client
先创建客户端对象,指定目标服务的主机和端口:
cpp
// 访问本地8080端口的服务
httplib::Client client("localhost", 8080);
// 访问远程服务,比如百度(注意端口80)
httplib::Client baidu_client("www.baidu.com", 80);
发送请求
客户端支持 GET/POST/PUT/DELETE 等请求,以常用的 GET 和 POST 为例:
- GET 请求 :如果需要带请求头,传
Headers
对象;不需要就传空。
cpp
// 发送GET /hi 请求,不带请求头
auto res = client.Get("/hi");
// 检查响应是否成功(状态码200)
if (res && res->status == 200) {
std::cout << "Response: " << res->body << std::endl;
}
- POST 请求 :需要传请求体(比如 JSON 字符串)和内容类型(
content_type
):
cpp
// POST一个JSON数据
std::string json_body = R"({"name": "cpp-httplib", "version": "0.12.0"})";
auto res = client.Post("/api/save", json_body, "application/json");
四、实战:写一个 "Hello World" 服务器
光说不练假把式,我们基于文档里的示例,写一个完整的 HTTP 服务器 ------ 访问http://localhost:8080/hi
时,返回一个 HTML 页面,显示 "Hello World"。
1. 完整代码(main.cc)
cpp
#include "cpp-httplib/httplib.h"
#include <iostream>
// 封装一个HelloServer类,让代码更规整
class HelloServer {
public:
// 构造函数:初始化端口,注册路由
HelloServer(int port) : _port(port) {
// 注册GET /hi 的处理器:调用HelloWorld方法
_server.Get("/hi", std::bind(
&HelloServer::HelloWorld, // 要绑定的成员函数
this, // 指向当前对象的指针
std::placeholders::_1, // 占位符:第一个参数(Request)
std::placeholders::_2 // 占位符:第二个参数(Response)
));
}
// 启动服务器
void run() {
std::cout << "Starting server on http://0.0.0.0:" << _port << "..." << std::endl;
// 监听0.0.0.0(所有网卡)的_port端口
if (!_server.listen("0.0.0.0", _port)) {
std::cerr << "Failed to start server! Maybe port " << _port << " is used." << std::endl;
}
}
private:
// 处理GET /hi 的逻辑
void HelloWorld(const httplib::Request &req, httplib::Response &rsp) {
// 1. 构造响应体:HTML内容
std::string html_body = R"(
<!DOCTYPE html>
<html>
<head>
<title>cpp-httplib Test</title>
<style>h1 { color: #2c3e50; text-align: center; margin-top: 50px; }</style>
</head>
<body>
<h1>Hello World! This is cpp-httplib Server</h1>
</body>
</html>
)";
// 2. 设置响应内容和类型(text/html)
rsp.set_content(html_body, "text/html");
// 3. 设置HTTP状态码:200 OK
rsp.status = 200;
// 4. 可选:加个响应头(比如设置字符编码)
rsp.set_header("Content-Type", "text/html; charset=utf-8");
}
int _port; // 服务器端口
httplib::Server _server; // cpp-httplib服务器对象
};
int main() {
// 创建服务器实例,端口8080
HelloServer server(8080);
// 启动服务器(会阻塞当前线程)
server.run();
return 0;
}
2. 代码解析
-
类封装 :把服务器逻辑放到
HelloServer
类里,比写全局函数更规整,后续加路由(比如/about
)也方便。 -
路由绑定 :用
std::bind
把成员函数HelloWorld
绑定到/hi
路由 ------ 因为Handler
需要的是全局函数或无捕获的 lambda,而成员函数需要this
指针,所以必须用bind
。 -
响应构造:不仅返回了 HTML 内容,还加了 CSS 样式和字符编码头,避免中文乱码(虽然这里没中文,但好习惯要养成)。
五、编译与运行:就一条命令
cpp-httplib 需要 C++11 及以上标准,推荐用 C++17(兼容性更好),编译时还要加-pthread
(因为库内部用了线程)。
1. 编译命令
在代码目录下执行:
cpp
g++ -std=c++17 main.cc -o hello_server -pthread
-
-std=c++17
:指定 C++17 标准。 -
-o hello_server
:生成可执行文件名为hello_server
。 -
-pthread
:链接线程库,必须加,否则会编译报错。
2. 运行与测试
- 启动服务器:
cpp
./hello_server
看到Starting server on ``http://0.0.0.0:8080``...
就说明启动成功了。
- 测试访问:
-
用浏览器打开
http://localhost:8080/hi
,会看到居中的 "Hello World" 标题。 -
用 curl 命令测试(适合服务器环境):
会输出完整的 HTML 代码。
- 停止服务器 :按
Ctrl+C
即可。
六、注意事项:避坑指南
-
端口占用:如果启动时报 "Failed to start server",大概率是 8080 端口被其他程序占用,换个端口(比如 8081)就行。
-
HTTPS 支持:如果需要跑 HTTPS,编译时要链接 OpenSSL 库:
cpp
g++ -std=c++17 main.cc -o hello_server -pthread -lssl -lcrypto
然后创建SSLServer
对象(而不是Server
):
cpp
httplib::SSLServer ssl_server;
- 跨平台编译:
-
Windows:用 MinGW 的 g++,命令和 Linux 一样;或用 MSVC(VS2019 及以上),在项目属性里加
/std:c++17
和/MT
(静态链接)。 -
macOS:和 Linux 完全一样,直接用系统自带的 g++ 或 clang++。
- 路由匹配 :支持模糊匹配,比如
/user/:id
能匹配/user/123
,通过req.params["id"]
获取参数;/file/*
能匹配/file/a.txt
、/file/doc/b.pdf
,通过req.path
获取完整路径。
七、总结
cpp-httplib 的优势就在于 "轻量" 和 "易用"------ 不用花半天搭环境,一个头文件 + 几行代码就能跑起 HTTP 服务,非常适合快速开发、原型验证,或是给 C++ 项目加个简单的 Web 接口。
如果你后续需要更复杂的功能(比如拦截器、会话管理),可以去看它的官方文档(有更多示例,比如文件上传、异步客户端)。