从Python Requests到libcpr/cpr:C++开发者的无缝过渡
【免费下载链接】cpr 项目地址: https://gitcode.com/gh_mirrors/cpr/cpr
你是否在C++项目中苦于处理复杂的网络请求?是否怀念Python Requests库简洁直观的API?本文将带你实现从Python Requests到C++网络库libcpr/cpr的平滑过渡,用熟悉的编程模式解决C++网络编程难题。读完本文,你将能够:掌握libcpr的核心API,实现常见HTTP请求,处理认证、超时等高级功能,以及编写异步网络代码。
为什么选择libcpr/cpr?
libcpr/cpr(C++ Requests)是一个基于libcurl的C++网络库,灵感来源于Python Requests项目。它解决了原生libcurl接口复杂、容易出错的问题,利用C++17的语言特性,将网络请求封装为简洁易懂的API。
主要优势:
- 与Python Requests相似的直观API设计
- 完整支持HTTP/HTTPS协议
- 线程安全的libcurl访问
- 支持异步请求和连接池
- 简洁的错误处理机制
项目核心文件结构:
- 主头文件:include/cpr/cpr.h
- 请求实现:cpr/session.cpp、cpr/response.cpp
- 测试示例:test/get_tests.cpp、test/post_tests.cpp
环境准备与安装
系统要求
- C++17兼容编译器(GCC、Clang等)
- CMake 3.14+
- OpenSSL开发库(用于HTTPS支持)
安装方式
CMake FetchContent(推荐)
在你的CMakeLists.txt中添加:
include(FetchContent)
FetchContent_Declare(cpr GIT_REPOSITORY https://gitcode.com/gh_mirrors/cpr/cpr
GIT_TAG 3b15fa82ea74739b574d705fea44959b58142eb8)
FetchContent_MakeAvailable(cpr)
target_link_libraries(your_target_name PRIVATE cpr::cpr)
手动编译安装
git clone https://gitcode.com/gh_mirrors/cpr/cpr
cd cpr && mkdir build && cd build
cmake .. -DCPR_USE_SYSTEM_CURL=ON
cmake --build . --parallel
sudo cmake --install .
在项目中使用:
find_package(cpr REQUIRED)
target_link_libraries(your_target_name PRIVATE cpr::cpr)
核心API对比:Python Requests vs libcpr
基本GET请求
Python Requests:
import requests
response = requests.get('https://api.example.com/data',
params={'key': 'value'},
timeout=5)
print(response.status_code)
print(response.json())
libcpr/cpr:
#include <cpr/cpr.h>
#include <iostream>
int main() {
cpr::Response r = cpr::Get(cpr::Url{"https://api.example.com/data"},
cpr::Parameters{{"key", "value"}},
cpr::Timeout{5000}); // 超时时间,单位毫秒
std::cout << r.status_code << std::endl;
std::cout << r.text << std::endl;
return 0;
}
请求参数与响应处理
Python Requests:
response = requests.get('https://api.example.com/data',
params={'page': 1, 'limit': 10})
print(f"状态码: {response.status_code}")
print(f"响应头: {response.headers['Content-Type']}")
print(f"响应内容: {response.text}")
libcpr/cpr:
cpr::Response r = cpr::Get(cpr::Url{"https://api.example.com/data"},
cpr::Parameters{{"page", "1"}, {"limit", "10"}});
std::cout << "状态码: " << r.status_code << std::endl;
std::cout << "响应头: " << r.header["content-type"] << std::endl;
std::cout << "响应内容: " << r.text << std::endl;
高级功能实现
认证处理
基本认证 (Basic Authentication)
Python Requests:
response = requests.get('https://api.example.com/secret',
auth=('user', 'pass'))
libcpr/cpr:
cpr::Response r = cpr::Get(cpr::Url{"https://api.example.com/secret"},
cpr::Authentication{"user", "pass", cpr::AuthMode::BASIC});
Bearer Token认证
Python Requests:
headers = {'Authorization': 'Bearer YOUR_TOKEN'}
response = requests.get('https://api.example.com/data', headers=headers)
libcpr/cpr:
cpr::Response r = cpr::Get(cpr::Url{"https://api.example.com/data"},
cpr::Bearer{"YOUR_TOKEN"});
POST请求与数据提交
表单数据提交
Python Requests:
data = {'name': 'John', 'age': '30'}
response = requests.post('https://api.example.com/users', data=data)
libcpr/cpr:
cpr::Response r = cpr::Post(cpr::Url{"https://api.example.com/users"},
cpr::Payload{{"name", "John"}, {"age", "30"}});
JSON数据提交
Python Requests:
import json
data = {'name': 'John', 'age': 30}
response = requests.post('https://api.example.com/users',
json=data)
libcpr/cpr:
cpr::Response r = cpr::Post(cpr::Url{"https://api.example.com/users"},
cpr::Header{{"Content-Type", "application/json"}},
cpr::Body{R"({"name":"John","age":30})"});
文件上传
Python Requests:
files = {'file': open('document.pdf', 'rb')}
response = requests.post('https://api.example.com/upload', files=files)
libcpr/cpr:
cpr::Response r = cpr::Post(cpr::Url{"https://api.example.com/upload"},
cpr::Multipart{{"file", cpr::File{"document.pdf"}}});
异步请求处理
异步GET请求
Python Requests (使用requests-futures):
from requests_futures.sessions import FuturesSession
session = FuturesSession()
future = session.get('https://api.example.com/data')
# 执行其他任务
response = future.result()
print(response.text)
libcpr/cpr:
cpr::AsyncResponse future = cpr::GetAsync(cpr::Url{"https://api.example.com/data"});
// 执行其他任务
cpr::Response r = future.get();
std::cout << r.text << std::endl;
多异步请求
libcpr/cpr:
std::vector<cpr::AsyncResponse> futures;
futures.emplace_back(cpr::GetAsync(cpr::Url{"https://api.example.com/data1"}));
futures.emplace_back(cpr::GetAsync(cpr::Url{"https://api.example.com/data2"}));
for (auto& future : futures) {
cpr::Response r = future.get();
std::cout << "状态码: " << r.status_code << ", 内容: " << r.text << std::endl;
}
超时与错误处理
设置超时
Python Requests:
try:
response = requests.get('https://api.example.com/data',
timeout=5) # 5秒超时
except requests.exceptions.Timeout:
print("请求超时")
libcpr/cpr:
cpr::Response r = cpr::Get(cpr::Url{"https://api.example.com/data"},
cpr::Timeout{5000}, // 5000毫秒超时
cpr::ConnectTimeout{2000}); // 连接超时2秒
if (r.status_code == 0) {
std::cerr << "请求超时或失败: " << r.error.message << std::endl;
}
错误处理
Python Requests:
try:
response = requests.get('https://api.example.com/data')
response.raise_for_status()
except requests.exceptions.HTTPError as e:
print(f"HTTP错误: {e}")
except requests.exceptions.RequestException as e:
print(f"请求异常: {e}")
libcpr/cpr:
cpr::Response r = cpr::Get(cpr::Url{"https://api.example.com/data"});
if (!r.error) {
if (r.status_code >= 200 && r.status_code < 300) {
// 请求成功
std::cout << r.text << std::endl;
} else {
std::cerr << "HTTP错误: " << r.status_code << std::endl;
}
} else {
std::cerr << "请求错误: " << r.error.message << std::endl;
}
会话管理与高级配置
会话复用
Python Requests:
with requests.Session() as session:
session.headers.update({'User-Agent': 'My App'})
session.get('https://api.example.com/login', params={'token': 'abc'})
response = session.get('https://api.example.com/data')
libcpr/cpr:
cpr::Session session;
session.SetUrl(cpr::Url{"https://api.example.com"});
session.SetHeader(cpr::Header{{"User-Agent", "My App"}});
// 登录
session.SetParameters(cpr::Parameters{{"token", "abc"}});
session.Get();
// 复用会话获取数据
session.SetUrl(cpr::Url{"https://api.example.com/data"});
cpr::Response response = session.Get();
实战示例:REST API客户端
下面是一个完整的libcpr/cpr使用示例,实现一个简单的REST API客户端:
#include <cpr/cpr.h>
#include <iostream>
#include <nlohmann/json.hpp> // 需要安装nlohmann/json库
using json = nlohmann::json;
class ApiClient {
private:
std::string base_url;
cpr::Session session;
public:
ApiClient(std::string url) : base_url(std::move(url)) {
// 设置通用头部
session.SetHeader(cpr::Header{
{"Content-Type", "application/json"},
{"User-Agent", "libcpr Client"}
});
// 设置超时
session.SetTimeout(cpr::Timeout{10000});
}
void set_auth_token(const std::string& token) {
session.SetHeader(cpr::Header{{"Authorization", "Bearer " + token}});
}
json get(const std::string& endpoint) {
session.SetUrl(cpr::Url{base_url + endpoint});
auto response = session.Get();
if (response.status_code != 200) {
throw std::runtime_error("GET请求失败: " + std::to_string(response.status_code));
}
return json::parse(response.text);
}
json post(const std::string& endpoint, const json& data) {
session.SetUrl(cpr::Url{base_url + endpoint});
session.SetBody(cpr::Body{data.dump()});
auto response = session.Post();
if (response.status_code < 200 || response.status_code >= 300) {
throw std::runtime_error("POST请求失败: " + std::to_string(response.status_code));
}
return json::parse(response.text);
}
};
int main() {
try {
ApiClient client("https://api.example.com/v1/");
client.set_auth_token("YOUR_AUTH_TOKEN");
// 获取数据
auto users = client.get("users");
std::cout << "用户列表: " << users.dump(4) << std::endl;
// 创建新用户
json new_user = {{"name", "New User"}, {"email", "user@example.com"}};
auto created_user = client.post("users", new_user);
std::cout << "创建用户: " << created_user.dump(4) << std::endl;
} catch (const std::exception& e) {
std::cerr << "发生错误: " << e.what() << std::endl;
return 1;
}
return 0;
}
总结与进阶
通过本文的介绍,你已经掌握了libcpr/cpr的核心用法,能够实现从Python Requests到C++的平滑过渡。libcpr/cpr提供了与Python Requests相似的API设计,同时保持了C++的性能优势。
进阶学习资源:
- 官方测试用例:test/目录包含各种功能的示例代码
- 异步编程:探索cpr/async.cpp和cpr/threadpool.cpp了解异步实现原理
- 拦截器功能:通过test/interceptor_tests.cpp学习请求/响应拦截
libcpr/cpr是一个活跃发展的项目,定期更新新功能和改进。建议关注项目的README.md获取最新信息和版本更新。
希望本文能帮助你在C++项目中更高效地处理网络请求。如果你有任何问题或使用心得,欢迎在评论区分享交流!
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考



