httplib库的使用,支持http/https httplib库简介 1. 文件目录 2. client端 2.1 快速搭建一个client端 2.2 HTTPS 2.3 下载文件 2.4 GET大数据 2.5 POST大数据 2.6 上传文件 3. server端的简单使用 4.其他资料 httplib库简介 httplib库是一个以C++11特性编写的库,所以编译器也需要能支持C++11的。库在使用时只需包含一个头文件即可,非常方便。 下载地址 注意:此库为线程阻塞,使用时还请注意。 1. 文件目录 下载后的包解压后有如下文件 其中httplib.h为库的头文件,使用时只需要将此头文件包含在你的代码中即可。 example:此文件夹中有作者分享的一些代码示例,使用时可参考。 split.py:此文件为python执行文件,如果你还是想用.h和.cpp的方式将库加入到你的工程中,可以运行此文件。执行成功后会在同目录下生成一个out文件夹,里面便包含了分离的.cc和.h文件。 2. client端 2.1 快速搭建一个client端 使用时需先引入命名空间using namespace httplib,当然也可以在调用相关类时直接加上httplib::域。 如下直接建立一个http的client端,连接到本地 1234端口,获取链接 /hi下的数据,数据的主体都在返回的res->body中。 #include <httplib.h> #include <iostream> int main(void) { httplib::Client cli("localhost", 1234); if (auto res = cli.Get("/hi")) { if (res->status == 200) { std::cout << res->body << std::endl; } } else { auto err = res.error(); ... } } res是Response类对象实例,其定义为 我们一般主要引用body,这里面就是数据。头字段的话则包含在header中。 链接的错误信息返回在res.error中,error定义为 enum Error { Success = 0, Unknown, Connection, BindIPAddress, Read, Write, ExceedRedirectCount, Canceled, SSLConnection, SSLLoadingCerts, SSLServerVerification, UnsupportedMultipartBoundaryChars }; 链接成功后,通过Get的url返回的状态码在res->status中,此状态码即为HTTP状态码。 2.2 HTTPS 库默认使用的是HTTP,如果要使用HTTPS,需在程序中定义 #define CPPHTTPLIB_OPENSSL_SUPPORT 使用时可参考 #ifdef CPPHTTPLIB_OPENSSL_SUPPORT httplib::SSLClient client(ser_ip, ser_port); //https client.enable_server_certificate_verification(true); //看实际情况使能 client.set_ca_cert_path("ca-bundle.crt"); //设置ca证书 #else httplib::Client client("127.0.0.1:80"); //http #endif 另外注意:使用HTTPS方式时,需引入ssl库,且当前库只支持ssl version 1.1.1版本。 2.3 下载文件 下载可以使用GET方法,并且可以通过以下代码获取下载文件的进度(代码将获取到的数据保存为down_file.tar格式的文件,因为传递过程中是以二进制数据传递,文件类型可以根据实际情况保存,此只是做个示例): if(auto res = client.Get("/hi", [](uint64_t len, uint64_t total) { printf("%lld / %lld bytes => %d%% complete\n",len, total,(int)(len*100/total)); return true; // return 'false' if you want to cancel the request. })) { printf("status:%d\n",res->status); if(res->status == 200) { std::ofstream out; out.open("down_file.tar", std::ios_base::binary | std::ios::out); printf("savefile!\n"); if(out.is_open()) { out<<res->body; out.close(); printf("down load file finished!\n"); } else { printf("open file error!\n"); } } } else { printf("url connect failed! error = %d\n",(int)res.error()); } 2.4 GET大数据 如果GET数据太大,可使用如下的方式接收: std::string body; auto res = cli.Get("/large-data", [&](const char *data, size_t data_length) { body.append(data, data_length); return true; }); 2.5 POST大数据 笔者在使用过程中将一个200M以上的文件读取后POST会报段错误,原因是读取文件后POST过程中会有拷贝过程,文件或者数据量太大时会有问题。可使用如下方法POST: std::string body = ...; auto res = cli.Post( "/stream", body.size(), [&](size_t offset, size_t length, DataSink &sink) { sink.write(body.data() + offset, length); return true; // return 'false' if you want to cancel the request. }, "text/plain"); 2.6 上传文件 上传文件需使用MultipartFormData,笔者在使用过程中发现,利用此方法上传文件有限制,文件太大时会报段错误(笔者测试时使用的是200多M的文件,具体临界值没有测试)。所以建议在读取文件时加上文件大小限制的判断。 #ifdef CPPHTTPLIB_OPENSSL_SUPPORT httplib::SSLClient client(ser_ip, ser_port); client.enable_server_certificate_verification(true); //看实际情况使能 client.set_ca_cert_path("ca-bundle.crt"); #else httplib::Client client("127.0.0.1:80"); #endif std::string body = ""; //此处添加读取上传文件的代码,将读取到的数据存入body中 httplib::MultipartFormData updataData; updataData.name = "upfile"; updataData.content = body; updataData.filename = file_name; updataData.content_type = content_type; httplib::MultipartFormDataItems items; items.push_back(updataData); if (auto res = client.Post(file_upload_url.c_str(), items)) { if (res->status != 200) { printf("error status = %d\n",res->status); return -4; } else { return 0; //upload file success } } else { printf("url connect failed! error = %d\n",(int)res.error()); return -5; } } else { printf("read upload file error\n"); return -3; } 3. server端的简单使用 服务端程序可参考如下代码,程序线程会阻塞在listen处,因此建议另开一个线程来监听。 #define SERVER_CERT_FILE "./cert.pem" #define SERVER_PRIVATE_KEY_FILE "./key.pem" int main(void) { #ifdef CPPHTTPLIB_OPENSSL_SUPPORT SSLServer svr(SERVER_CERT_FILE, SERVER_PRIVATE_KEY_FILE); #else Server svr; #endif if (!svr.is_valid()) { printf("server has an error...\n"); return -1; } svr.Get("/hi", [](const Request& req, Response& res) { res.set_content("Hello World!", "text/plain"); }); svr.Get(R"(/numbers/(\d+))", [&](const Request& req, Response& res) { auto numbers = req.matches[1]; res.set_content(numbers, "text/plain"); }); svr.Get("/body-header-param", [](const Request& req, Response& res) { if (req.has_header("Content-Length")) { auto val = req.get_header_value("Content-Length"); } if (req.has_param("key")) { auto val = req.get_param_value("key"); } res.set_content(req.body, "text/plain"); }); svr.Get("/stop", [&](const Request& req, Response& res) { svr.stop(); }); svr.listen("localhost", 1234); return 0; } 4.其他资料 此外还有几篇针对httplib库写的不错的文章,一并收藏在此: C++ httplib 解读 cpp-httplib库的原理 C++ Http/Https服务器和客户端库cpp-httplib
标签:body,文件,httplib,http,res,client,https,return From: https://www.cnblogs.com/kn-zheng/p/17554053.html