当前位置: 首页 > backend >正文

CppCon 2015 学习:C++ Requests

HTTP高层次概述

HTTP(超文本传输协议)是用于在客户端和服务器之间交换信息的一种协议。其核心概念包括 请求方法(或称 HTTP动词,Verbs),它决定了客户端对资源的操作方式。
常见的HTTP动词有:

  1. GET:请求服务器上的资源。例如,浏览器访问一个网页时,会发送一个GET请求。
    • 示例GET /index.html
    • 说明:客户端请求获取指定的资源(如一个网页或图片)。
  2. PUT:将数据上传到指定位置,通常用于创建或更新资源。
    • 示例PUT /user/1234
    • 说明:客户端发送新的数据(如更新用户信息)并存储在服务器上指定的资源位置。
  3. DELETE:请求删除指定的资源。
    • 示例DELETE /user/1234
    • 说明:客户端请求服务器删除指定的资源(如删除一个用户)。
      这些基本操作是HTTP协议的核心,基本上涵盖了与资源交互所需的所有方法。理解这些HTTP动词,有助于我们更好地设计和使用基于HTTP的应用程序。

总结:

  • HTTP动词(Verbs):主要包括 GETPUTDELETE,这些方法用来获取数据、上传数据和删除数据。

是不是过于天真?

当我们仅仅谈论 HTTP 的基本动词(如 GET、PUT 和 DELETE)时,确实显得有些过于简单了。在现实世界中,HTTP 协议的使用远不止这些基本操作。实际的网络应用中还涉及许多复杂的内容,比如 认证头部信息Cookie、会话、代理等,这些都在 HTTP 请求和响应的过程中起着至关重要的作用。

这些复杂的部分包括:

  1. 认证(Authentication)
    • HTTP 本身没有内建的用户认证机制,但它提供了多个认证方式,最常见的有:
      • Basic Authentication:通过用户名和密码在 HTTP 头中传递。
      • Bearer Token:用于 API 认证,常见于 OAuth2 等授权框架。
    • 这些认证方式确保了请求来自合法用户或系统。
  2. 头部信息(Headers)
    • HTTP 头部是传递额外信息的地方,包括但不限于:
      • Content-Type:指定请求或响应的内容类型(如 JSON、HTML、图片等)。
      • Authorization:用于传递认证信息(如 Bearer Token)。
      • User-Agent:包含发出请求的浏览器或客户端的类型信息。
      • Accept:客户端希望服务器返回的响应内容类型(如 Accept: application/json)。
  3. Cookie、会话(Sessions)
    • Cookies:是小型数据片段,通过浏览器或客户端与服务器之间交换,用于存储用户状态,如登录信息。
    • Sessions:会话是服务器端存储的会话数据,用来追踪用户的活动。通常,用户第一次登录时,服务器创建会话并返回一个会话 ID,浏览器将其存储为 Cookie,在后续请求中发送回服务器。
  4. 代理(Proxies)
    • HTTP 请求可能通过代理服务器转发。代理用于多种用途,包括缓存、负载均衡、匿名化等。
    • 代理服务器处理来自客户端的请求,然后将其转发给实际的服务器,客户端对实际的服务器不直接接触。

总结:

HTTP 协议的使用不仅仅局限于简单的请求方法,还涉及认证、头部信息、会话管理、代理等多个方面。要深入理解和应用 HTTP,必须了解这些高级功能和它们如何协同工作。

“HTTP should be as simple as a print statement” - Kenneth Reitz

这句话出自 Kenneth Reitz,他是 Python Requests 库的作者之一。其含义是,HTTP 的使用应该尽可能简化,像打印一条消息一样直观和简单。

简化 HTTP 的目标

  1. 简洁的接口
    • HTTP 请求应该简单易用,就像你调用一个 print() 函数一样,不需要关心底层的复杂细节。开发者不应该被繁琐的 HTTP 协议细节所困扰,而是能够快速有效地发起请求并得到响应。
    • Requests 库就是基于这个理念的设计,它简化了传统的 HTTP 请求过程,让开发者可以通过简单的 Python 代码发起 HTTP 请求,背后却隐藏了许多复杂的操作(如头部设置、编码、认证等)。
  2. 专注于业务逻辑
    • 通过简化 HTTP 的使用,开发者可以将精力集中在应用程序的核心逻辑上,而不是 HTTP 的实现细节。比如,只需要关心如何发送请求和处理响应,而不是如何处理不同的 HTTP 方法、状态码、头部等。
    • 例如,在 Requests 库中,发送一个 GET 请求就只需要简单地写 requests.get("http://example.com"),而不需要编写复杂的底层代码。
  3. 提升开发体验
    • HTTP 本身是一个强大而复杂的协议,但在日常开发中,我们并不需要对这些复杂的底层实现有太多了解。简化它可以让开发者体验更加流畅,减少出错的机会。
    • “如打印语句一样简单” 的哲学意味着希望开发者能像调用常规函数那样简单地进行 HTTP 请求,无需理解和处理大量的 HTTP 协议细节。

总结

Kenneth Reitz 的这句话强调的是通过简化 HTTP 请求的方式,提升开发效率和用户体验。在现代开发中,我们追求的是一种开发者友好的工具,让复杂的操作变得简单,开发者只需专注于应用的核心业务逻辑,而不用被底层细节拖累。

这段代码展示了如何使用 cpr(C++ Requests)库来发起一个 HTTP GET 请求,并打印响应的内容。

代码解析:

#include <cpr.h> // 引入 cpr 库
#include <iostream> // 引入标准输入输出库
int main(int argc, char** argv) {// 发起一个 HTTP GET 请求,目标 URL 为 https://httpbin.org/getauto r = cpr::Get(Url{"https://httpbin.org/get"});// 输出响应内容,即返回的网页文本std::cout << r.text << std::endl;
}

关键点解释:

  1. cpr::Get:
    • cpr::Getcpr 库中的一个函数,用于发送 HTTP GET 请求。
    • 传入的 Url{“https://httpbin.org/get”} 是指定请求的目标 URL,这里使用了 httpbin.org 这个网站,它会返回请求的内容作为响应。
  2. r.text:
    • rcpr::Response 类型的对象,它包含了 HTTP 请求的响应。
    • r.textcpr::Response 对象中的一个成员变量,它保存了响应的正文内容(即服务器返回的数据,通常是 HTML 或 JSON 格式的文本)。
  3. std::cout:
    • std::cout 是 C++ 中用于输出文本到控制台的标准输出流。
    • std::endl 用于输出换行符并刷新缓冲区。

运行结果:

当你运行这段程序时,它会向 https://httpbin.org/get 发送一个 GET 请求,然后打印出响应的文本内容。 httpbin.org 会返回包含请求信息的 JSON 数据。
例如,响应内容可能会像这样:

{"args": {},"headers": {"Accept": "*/*","Host": "httpbin.org","User-Agent": "cpr/1.6.2"},"origin": "xxx.xxx.xxx.xxx","url": "https://httpbin.org/get"
}

总结:

这段代码展示了如何使用 C++ 的 cpr 库来简化 HTTP 请求的操作,发起 GET 请求并输出服务器的响应。cpr 库使得 C++ 中的 HTTP 请求变得更简单易用,类似于 Python 中的 requests 库。

这段代码展示了如何使用 libcurl 库来发送 HTTP GET 请求,并处理返回的响应。与 cpr 库相比,libcurl 需要更多的设置和配置,代码也较为冗长。

代码解析:

#include <curl/curl.h> // 引入 libcurl 库
#include <iostream>     // 引入标准输入输出库
#include <string>       // 引入字符串库
// 回调函数,用于处理从 HTTP 响应中读取的数据
size_t write(void* ptr, size_t size, size_t nmemb, std::string* data) { data->append((char*) ptr, size * nmemb);  // 将响应数据附加到 data 字符串中return size * nmemb;  // 返回已处理的数据大小
}
int main(int argc, char** argv) { // 初始化 curl 会话auto curl = curl_easy_init(); // 设置 URL(请求的地址)curl_easy_setopt(curl, CURLOPT_URL, "https://httpbin.org/get");// 禁用进度信息curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 1L);// 设置用户代理curl_easy_setopt(curl, CURLOPT_USERAGENT, "curl/7.42.0");// 开启 TCP Keep-Alivecurl_easy_setopt(curl, CURLOPT_TCP_KEEPALIVE, 1L);// 创建用于存储响应数据的字符串std::string response_text;// 设置写回调函数,用于处理响应数据curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write);// 设置写数据的目标curl_easy_setopt(curl, CURLOPT_WRITEDATA, &response_text);// 执行 HTTP 请求curl_easy_perform(curl);// 清理 curl 会话curl_easy_cleanup(curl); // 置空 curl 对象curl = NULL;// 输出响应数据std::cout << response_text << std::endl; 
}

关键点解释:

  1. curl_easy_init():
    • 初始化一个 curl 会话,并返回一个 CURL* 类型的指针。这个指针用于后续的请求设置和执行。
  2. curl_easy_setopt():
    • 用于设置 curl 会话的各种选项,例如请求的 URL、HTTP 请求头(如 User-Agent)和回调函数等。
    • 在这段代码中,设置了 CURLOPT_URL(目标 URL)、CURLOPT_NOPROGRESS(禁止显示下载进度)、CURLOPT_USERAGENT(设置用户代理)、CURLOPT_TCP_KEEPALIVE(开启 TCP keep-alive)等选项。
  3. write() 回调函数:
    • 这个回调函数是 libcurl 提供的,用来处理接收到的数据。在每次读取到响应数据时,write() 函数会被调用,并将接收到的数据追加到 response_text 字符串中。
    • 函数返回的 size * nmemb 值是 libcurl 期望接收到的数据量。size 是每个数据块的大小,nmemb 是数据块的数量。
  4. curl_easy_perform():
    • 执行 HTTP 请求,libcurl 会使用先前设置的选项来发送请求并接收响应。响应数据会通过回调函数(write())写入 response_text
  5. curl_easy_cleanup():
    • 清理并释放 curl_easy_init() 返回的 CURL* 资源。
  6. 输出响应:
    • std::cout 输出从服务器返回的响应内容(response_text)。

cpr 库的比较:

  • 简洁性
    • cpr 的代码更加简洁和易读,因为它封装了很多复杂的细节(如回调函数、处理响应数据等)。
    • libcurl 的 API 比较底层,需要开发者手动处理回调函数来获取响应数据,而且配置选项也更多。
  • 灵活性
    • libcurl 提供了更多的配置选项和控制能力,例如可以自定义请求头、启用代理、处理 SSL/TLS 等。对于需要更精细控制的场景,libcurl 是一个更灵活的选择。
    • cpr 则是为了简化常见的 HTTP 请求操作,适合不需要复杂配置的场景。
  • 依赖性
    • cpr 库是基于 libcurl 封装的,所以在使用 cpr 时底层依赖了 libcurl。如果已经使用了 libcurl,那么直接使用 libcurl 可能会更合适,特别是需要进行复杂的 HTTP 请求配置时。
    • libcurl 是一个独立的库,需要额外配置和链接。

总结:

  • 如果你希望简洁地发起 HTTP 请求并获取响应,cpr 是一个非常方便的库,代码量少,易于理解。
  • 如果你需要更灵活的控制或者需要处理更复杂的 HTTP 请求,libcurl 提供了更多的功能,但使用起来较为复杂,代码量也更多。

这段代码展示了如何使用 Poco Libraries 进行 HTTP 请求。相比 libcurlcpr,Poco 提供了一个更高层次的 API,可以更方便地执行 HTTP 操作,同时依然允许你精确控制请求和响应。

代码解析:

#include <Poco/Net/......>  // 引入 Poco 的网络库
#include <iostream>          // 引入标准输入输出库
#include <string>            // 引入字符串库
int main(int argc, char** argv) { // 创建 URI 对象,并解析 URLPoco::URI uri("https://httpbin.org/get");// 创建 HTTPClientSession 对象,指定主机和端口Poco::Net::HTTPClientSession session(uri.getHost(), uri.getPort());// 获取 URL 的路径和查询部分std::string path(uri.getPathAndQuery());// 创建 HTTP 请求,使用 GET 方法Poco::Net::HTTPRequest request(Poco::Net::HTTPRequest::HTTP_GET, path, Poco::Net::HTTPMessage::HTTP_1_1);// 发送 HTTP 请求session.sendRequest(request);// 创建 HTTP 响应对象Poco::Net::HTTPResponse response;// 接收响应并读取流std::istream& in_stream = session.receiveResponse(response);// 创建输出流,保存响应数据std::ostringstream out_stream;// 将输入流中的数据拷贝到输出流中Poco::StreamCopier::copyStream(in_stream, out_stream);// 打印响应内容std::cout << out_stream.str() << std::endl; 
}

代码解析:

  1. Poco::URI:
    • 用来解析并处理 URL。通过 uri.getHost() 获取主机地址,通过 uri.getPort() 获取端口号,uri.getPathAndQuery() 获取路径和查询参数部分。
  2. Poco::Net::HTTPClientSession:
    • 用于管理与远程服务器的连接。在此代码中,它使用 uri.getHost()uri.getPort() 来初始化一个 HTTP 会话对象。HTTPClientSession 是实际的客户端会话,负责建立和维护与远程主机的连接。
  3. Poco::Net::HTTPRequest:
    • 创建一个 HTTP 请求对象。HTTPRequest::HTTP_GET 表示该请求是一个 GET 请求,path 是请求的目标路径(包括查询参数),HTTP_1_1 是 HTTP 协议版本。
  4. session.sendRequest(request):
    • 发送 HTTP 请求到服务器。
  5. Poco::Net::HTTPResponse:
    • 用于存储服务器的响应数据。session.receiveResponse(response) 接收服务器的响应,并返回一个输入流 in_stream
  6. Poco::StreamCopier::copyStream:
    • 将输入流 in_stream 中的数据复制到输出流 out_stream 中。最终,out_stream.str() 包含了服务器的响应内容。
  7. std::cout:
    • 输出服务器的响应内容到标准输出。

关键点:

  • Poco 的高层封装
    • Poco 提供的 API 更加面向对象,具有较高的封装性,相较于 libcurlcpr,Poco 更加简洁易用,尤其是处理 HTTP 请求和响应时,所需要的代码更少。
  • 灵活性与控制
    • 虽然 Poco 提供了简单的 API,但仍然保留了对 HTTP 请求细节的控制。你可以通过 HTTPRequestHTTPClientSession 自定义请求头、请求方法、响应处理等。
  • 代码简洁性
    • libcurl 的复杂配置和回调相比,Poco 提供了一种更加简洁和面向对象的方式,适合大多数常见的 HTTP 请求场景。

与其他库的对比:

  1. Poco vs. libcurl
    • Poco 提供了更简洁的接口,适用于快速开发和大部分场景,但 libcurl 提供的控制和功能更多,适用于更复杂的需求(例如,细粒度的连接控制、代理设置、SSL/TLS 等)。
  2. Poco vs. cpr
    • cpr 提供了非常简洁的接口,主要用于简单的 HTTP 请求。Poco 则在功能上提供了更多的控制能力,适用于需要更高灵活性和配置的场景。

总结:

  • Poco 是一个功能丰富、简洁易用的 C++ 网络库,适合大多数 HTTP 请求场景。它封装了许多底层细节,让开发者可以专注于业务逻辑,而不必过多关心底层实现。

这段代码展示了如何通过 cpr 库向一个 HTTP API 发送带有查询参数的 GET 请求,并输出响应结果。查询参数通过 Parameters 容器传递。

代码解析:

#include <cpr.h>       // 引入 cpr 库
#include <iostream>    // 引入标准输入输出库
int main(int argc, char** argv) { // 发送 GET 请求,并传递查询参数auto r = cpr::Get(Url{"https://httpbin.org/get"}, Parameters{{"key", "value"}}); // 打印响应的文本内容std::cout << r.text << std::endl; 
}

关键点:

  1. 查询参数传递:
    • cpr::Get 请求中,Parameters{{"key", "value"}} 代表了查询参数,它们将被自动编码为 URL 查询字符串并附加到 URL 中。
    • 例如,URL "https://httpbin.org/get?key=value" 会被发送到服务器。
  2. HTTP 请求:
    • 使用 cpr::Get 方法发送 GET 请求,URL 和查询参数作为参数传入。cpr::Get 是一个简单的 API,允许你快速发送 GET 请求。
  3. 响应处理:
    • 请求成功后,响应结果存储在 r.text 中。这里的 r 是一个 Response 对象,r.text 存储了从服务器接收到的响应内容。
  4. 输出响应:
    • 使用 std::cout 输出响应内容到标准输出流(通常是控制台)。

相关概念:

  • HTTP API 中的七个名词:
    1. uri: 代表了 URL,包含了请求的主机(getHost())、端口(getPort())和路径及查询字符串(getPathAndQuery())。
    2. session: HTTP 会话对象,负责发送请求(sendRequest())并接收响应(receiveResponse())。
    3. path: 请求路径,在构建 HTTPRequest 时传入。
    4. request: HTTP 请求对象,通过 sendRequest() 方法发送请求。
    5. response: HTTP 响应对象,通过 receiveResponse() 方法接收响应。
    6. in_stream: 响应的输入流,通过 copy_stream() 将响应数据复制到输出流。
    7. out_stream: 输出流,存储从响应中读取的数据。

高级特性:

  • 简化的 HTTP 请求接口:
    • 这段代码展示了一个非常简洁的 HTTP 请求方法,只需传入 URL 和查询参数,剩下的工作由 cpr 库自动处理。这种设计对于大多数常见的 HTTP 请求场景非常有效。
  • Query Parameters(查询参数):
    • 通过 Parameters{{"key", "value"}} 传递查询参数,可以很方便地在 URL 后添加 ?key=value,这些参数可以在服务器端被访问。

适用场景:

  • 95% 的用例:
    • 对于绝大多数简单的 HTTP 请求场景,使用像 cpr::Get 这样的简洁 API 足够应对。它简化了查询参数的添加、请求的发送和响应的处理,特别适用于需要快速实现功能的情况。

总结:

  • cpr 提供了一个易于使用的 API,可以轻松发送 HTTP 请求并处理响应。通过这种方法,开发者可以专注于业务逻辑,而不需要处理 HTTP 请求的底层细节。对于大多数常见的用例,这种简化的接口非常高效。

这段代码展示了如何使用 cpr 库实现 HTTP 请求的身份验证(Authentication)和 Digest 身份验证(Digest Authentication)。下面是每个示例的详细说明:

1. 基本认证(Basic Authentication):

#include <cpr.h>       // 引入 cpr 库
#include <iostream>    // 引入标准输入输出库
int main(int argc, char** argv) { // 使用基本认证(用户名和密码)发送 GET 请求auto r = cpr::Get(Url{"https://httpbin.org/get"}, Authentication{"user", "pass"}); // 打印响应的文本内容std::cout << r.text << std::endl; 
}

代码解析:

  • Authentication{"user", "pass"}:
    • 这是一个 HTTP 基本认证(Basic Authentication)对象,包含了用户名 "user" 和密码 "pass"
    • Authenticationcpr 库提供的一个类,用于处理 HTTP 请求时的基本认证信息。
    • 这个认证信息会被自动添加到 HTTP 请求头中,服务器使用这个信息来验证请求的合法性。
  • GET 请求:
    • cpr::Get 函数用于发送一个 GET 请求,URL 是 "https://httpbin.org/get",并传入认证信息。
  • 响应处理:
    • 响应结果被存储在 r.text 中,并通过 std::cout 输出。

2. Digest 认证(Digest Authentication):

#include <cpr.h>       // 引入 cpr 库
#include <iostream>    // 引入标准输入输出库
int main(int argc, char** argv) { // 使用 Digest 认证(用户名和密码)发送 GET 请求auto r = cpr::Get(Url{"https://httpbin.org/get"}, Digest{"user", "pass"}); // 打印响应的文本内容std::cout << r.text << std::endl; 
}

代码解析:

  • Digest{"user", "pass"}:
    • 这是一个 HTTP Digest 认证(Digest Authentication)对象,包含了用户名 "user" 和密码 "pass"
    • Digestcpr 库提供的另一个类,用于处理 Digest 认证信息。Digest 认证比基本认证更加安全,它不会直接将密码传输在请求头中,而是使用散列算法生成一个摘要(hash),然后将摘要值发送给服务器进行验证。
  • GET 请求:
    • 同样使用 cpr::Get 发送 GET 请求,URL 仍然是 "https://httpbin.org/get",并传入 Digest 认证信息。
  • 响应处理:
    • 与基本认证类似,响应结果存储在 r.text 中,并通过 std::cout 输出。

总结

  • 基本认证(Basic Authentication):
    • 在 HTTP 请求头中传递用户名和密码,易于实现,但安全性较低(因为密码明文传输)。
  • Digest 认证(Digest Authentication):
    • 提供比基本认证更高的安全性,密码不会在网络中直接传输,而是使用摘要算法生成的哈希值来验证请求。适用于要求更高安全性的场合。

区别

  • Basic Authentication: 更简单,适用于较低安全性需求的场合,但容易受到中间人攻击。
  • Digest Authentication: 更安全,通过加密的方式传输认证信息,减少了泄露密码的风险,适用于更高安全需求的场合。

这段代码展示了如何使用 cpr 库发送带有自定义 HTTP 头(Custom Headers)的 GET 请求。

代码解释:

#include <cpr.h>       // 引入 cpr 库
#include <iostream>    // 引入标准输入输出库
int main(int argc, char** argv) { // 发送一个 GET 请求,URL 是 "https://httpbin.org/get"// 请求中包含了一个自定义的请求头 "Accept: test/html"auto r = cpr::Get(Url{"https://httpbin.org/get"}, Headers{{"Accept", "test/html"}}); // 打印响应的文本内容std::cout << r.text << std::endl; 
}

代码解析:

  • 自定义请求头 (Headers{{"Accept", "test/html"}}):
    • 这是一个包含自定义请求头的对象。它使用了 Headers 类来构造一个 HTTP 请求头。
    • 在这里,我们设置了 "Accept" 头的值为 "test/html",意味着客户端告诉服务器它期望接收到 test/html 类型的响应。
    • 自定义头的作用是告诉服务器请求的内容类型或其他客户端的相关信息,服务器可以根据这些头来调整响应内容。
  • GET 请求:
    • cpr::Get 函数用于发送一个 GET 请求,URL 是 "https://httpbin.org/get",同时传递了自定义请求头。
  • 响应处理:
    • 请求的响应被存储在 r.text 中,并通过 std::cout 输出到终端。

结果:

  • 服务器接收到的请求会包括你设置的 Accept: test/html 头。服务器根据这个头来决定响应的格式。
  • 响应的文本内容(如 JSON 或 HTML 格式)会被打印在终端上。

总结:

  • 自定义请求头是 HTTP 协议的一部分,允许客户端提供额外的信息(如请求的内容类型、认证信息、缓存控制等)。
  • 通过 Headers 参数,你可以轻松地为 HTTP 请求添加自定义头部字段。
    这种方法对于需要与服务端进行特定通信的场合非常有用,特别是当你需要设置自定义的 Content-TypeAuthorization 等头信息时。

这段代码展示了如何使用 cpr 库发送带有 URL 编码的 POST 请求,并附带一些参数。

代码解释:

#include <cpr.h>       // 引入 cpr 库
#include <iostream>    // 引入标准输入输出库
int main(int argc, char** argv) { // 发送一个 POST 请求,URL 是 "https://httpbin.org/post"// 请求的正文部分使用 Payload 来传递键值对数据,数据会被 URL 编码auto r = cpr::Post(Url{"https://httpbin.org/post"}, Payload{{"key", "value"}, {"hello", "world"}});// 打印响应的文本内容std::cout << r.text << std::endl; 
}

代码解析:

  • POST 请求 (cpr::Post):
    • cpr::Post 是用来发送 HTTP POST 请求的方法。POST 请求通常用于提交数据给服务器,比如表单数据。
  • URL 编码的 Payload (Payload{{"key", "value"}, {"hello", "world"}}):
    • Payload 是 POST 请求中传递的数据部分,它是一个包含键值对的容器。
    • 这里的 { "key", "value" }{ "hello", "world" } 会作为 URL 编码的表单数据发送。即,key=valuehello=world 会以 URL 编码的格式附加到请求的 body 部分。
  • 请求 URL:
    • 请求发送到 "https://httpbin.org/post"httpbin.org 是一个提供各种 HTTP 请求测试和调试功能的公共网站。它会返回请求的详细信息,包括你发送的参数。
  • 响应:
    • 请求的响应会以 r.text 存储在 r 对象中。然后通过 std::cout 打印出来,响应内容通常是 JSON 格式,包含请求的详细信息,包括发送的 key=value 数据。

URL 编码:

  • 在 HTTP 协议中,URL 编码(或称为百分号编码)是一种将字符串中的特殊字符转换为 % 后跟相应的 ASCII 编码的格式。在 POST 请求中,数据通常以表单的形式进行 URL 编码传输,即使在发送时数据是通过表单的 application/x-www-form-urlencoded 编码格式发送的。

结果:

  • 服务器会接收到 POST 请求,并返回一个响应,包含你提交的表单数据。例如,响应可能类似于:
{"args": {},"data": "","files": {},"form": {"key": "value","hello": "world"},"json": null,"method": "POST","url": "https://httpbin.org/post"
}
  • 响应的 form 部分包含了你发送的表单数据,key=valuehello=world

总结:

  • URL 编码的 POST 请求是通过将数据作为键值对编码到请求正文中发送的。
  • cpr::Post 提供了简单的接口来进行 POST 请求,并可以通过 Payload 轻松地传递 URL 编码的数据。
  • 使用 httpbin.org 这样的服务可以方便地调试和查看请求的实际内容。

这段代码展示了如何使用 cpr 库发送 Multipart POST 请求,即包含文件或其他多部分数据的 POST 请求。

代码解释:

#include <cpr.h>       // 引入 cpr 库
#include <iostream>    // 引入标准输入输出库
int main(int argc, char** argv) { // 发送一个 Multipart POST 请求,URL 是 "https://httpbin.org/post"// 请求的正文部分使用 Multipart 来传递键值对数据auto r = cpr::Post(Url{"https://httpbin.org/post"}, Multipart{{"key", "long-string"}});// 打印响应的文本内容std::cout << r.text << std::endl; 
}

代码解析:

  • Multipart POST 请求 (cpr::PostMultipart{{"key", "long-string"}}):
    • cpr::Post 是用来发送 HTTP POST 请求的方法。不同于普通的 URL 编码 POST 请求,Multipart POST 请求通常用于上传文件或发送包含多个部分的数据(例如,文本和二进制数据)。
  • Multipart 数据 (Multipart{{"key", "long-string"}}):
    • Multipart 是一个容器,允许你在请求的 body 部分上传多个数据部分。
    • 在这个例子中,数据的一个部分是 "key""long-string",它们会作为 multipart/form-data 格式的一个部分发送。
    • 这种格式常用于上传文件和其他包含多个字段的表单数据。
  • 请求 URL:
    • 请求发送到 "https://httpbin.org/post",这是一个提供 HTTP 请求测试和调试功能的公共服务。
  • 响应:
    • 请求的响应会以 r.text 存储在 r 对象中。然后通过 std::cout 打印出来。响应通常是一个 JSON 格式的字符串,包含请求的详细信息。

Multipart 格式:

  • Multipart/form-data 是一种特殊的 HTTP 请求编码类型,允许通过 POST 请求发送多个部分的数据,每个部分的数据类型可以不同。
  • 最常见的用途是通过表单上传文件。在这种情况下,表单字段会被组织成多个部分,每部分包含数据和相关的元数据(如字段名、内容类型等)。
  • 每个部分 在 multipart 请求中都是独立的,包含自己的头信息和数据内容。

示例响应:

如果你向 httpbin.org 发送 Multipart POST 请求,响应的内容通常会像这样:

{"args": {},"data": "","files": {},"form": {"key": "long-string"},"json": null,"method": "POST","url": "https://httpbin.org/post"
}
  • form 部分包含了你通过 Multipart 请求发送的字段数据。在这个例子中,key 字段的值是 "long-string"

总结:

  • Multipart POST 请求 是通过发送包含多个数据部分的 POST 请求实现的。每部分可以包含不同类型的数据,通常用于上传文件或传输复杂的表单数据。
  • 使用 Multipart 在 cpr 库中很容易发送这样的请求。你可以通过 Multipart 传递字段名和字段值,cpr 库会自动将它们以正确的格式组织成 Multipart 请求体。
  • httpbin.org 是一个很好的在线服务,可以用来调试和查看你发送的 HTTP 请求及其响应。

CPR 库,它是一个 C++ HTTP 请求库。代码展示了如何发送一个包含文件的 POST 请求。

代码解析:

#include <cpr.h>  // 包含CPR库的头文件
#include <iostream>  // 包含输入输出流头文件
int main(int argc, char** argv) {// 发送一个POST请求到 https://httpbin.org/postauto r = cpr::Post(Url{"https://httpbin.org/post"},  // 请求的URLMultipart{{"key", "long-string"},  // 请求参数:key=long-string{"name", File{"path"}}});  // 请求参数:name=文件(路径为"path")// 打印返回的响应文本std::cout << r.text << std::endl;
}

代码的功能:

  1. 发送一个 POST 请求
    • 请求的URL是 https://httpbin.org/post
  2. 请求的参数
    • 使用 Multipart 类传递两个字段:
      • "key" 字段的值是一个长字符串 "long-string"
      • "name" 字段对应一个文件,文件路径是 "path"。这里 File{"path"} 代表将文件路径 "path" 作为 POST 请求的一部分发送。
  3. 输出响应结果
    • 请求发送后,响应的文本会通过 r.text 打印到控制台。

注意:

  • "path" 是文件的路径,实际使用时需要替换为本地文件的正确路径。
  • "long-string" 是一个示例字符串,实际使用时可以根据需求替换为其他数据。

中文总结:

这段代码示范了如何使用 CPR 库发送一个包含文件的 POST 请求,其中请求包括一个普通的字段(key)和一个文件字段(name)。响应内容将输出到控制台。

演示了如何使用 CPR 库发送一个更复杂的 HTTP GET 请求,包含了身份验证、请求头和请求参数。

代码解析:

#include <cpr.h>  // 包含CPR库的头文件
#include <iostream>  // 包含输入输出流头文件
int main(int argc, char** argv) {// 发送一个GET请求到 https://httpbin.org/postauto r = cpr::Get(Url{"https://httpbin.org/post"},  // 请求的URLAuthentication{"user", "pass"},  // 使用用户名和密码进行身份验证Headers{{"Accept", "test/html"}},  // 请求头,表示接受的响应格式为 test/htmlParameters{{"key", "value"}});  // 请求参数:key=value// 打印返回的响应文本std::cout << r.text << std::endl;
}

代码的功能:

  1. 发送一个 GET 请求
    • 请求的 URL 是 https://httpbin.org/post
  2. 身份验证
    • 请求中包含了基本的 身份验证,即用户名 "user" 和密码 "pass"。这通常用于需要身份验证的 API 请求。
  3. 请求头(Headers)
    • 设置请求头 Accept: test/html,表示客户端希望接收的响应类型是 test/html。通常这个字段告诉服务器,客户端能够处理的内容类型。
  4. 请求参数(Parameters)
    • 请求中带有一个查询参数 key=value。这通常是 URL 中的查询字符串部分。
  5. 输出响应结果
    • 请求发送后,响应的文本内容通过 r.text 输出到控制台。

中文总结:

这段代码演示了如何构造一个复杂的 GET 请求,它包含了以下几个部分:

  • 身份验证(使用用户名和密码)。
  • 请求头,指定了接受的响应格式为 test/html
  • 请求参数,通过 URL 查询字符串传递了 key=value
    响应的内容会通过 r.text 打印到控制台。

小提醒:

  • Authentication{"user", "pass"} 中的用户名和密码需要根据实际情况进行替换。
  • 这里使用的是 GET 请求,但 URL 后面没有显式地添加查询字符串,因为在 Parameters 中已经传递了查询参数。这会自动转化为 https://httpbin.org/post?key=value 这样的 URL。

这段代码展示了如何使用 CPR 库发送一个包含多种参数的 GET 请求,其中包含了身份验证、请求头和请求参数。其中特别强调了参数的顺序不重要,因为 CPR 库允许“无序”传递这些参数。

代码解析:

#include <cpr.h>  // 包含CPR库的头文件
#include <iostream>  // 包含输入输出流头文件
int main(int argc, char** argv) {// 发送一个GET请求到 https://httpbin.org/getauto r = cpr::Get(Url{"https://httpbin.org/get"},  // 请求的URLAuthentication{"user", "pass"},  // 使用用户名和密码进行身份验证Headers{{"Accept", "test/html"}},  // 请求头,表示接受的响应格式为 test/htmlParameters{{"key", "value"}});  // 请求参数:key=value// 打印返回的响应文本std::cout << r.text << std::endl;
}

代码的功能:

  1. 发送一个 GET 请求
    • 请求的目标 URL 是 https://httpbin.org/get
  2. 身份验证
    • 使用了基本的身份验证方式,提供了用户名 "user" 和密码 "pass",这会在请求中加入 Authorization 头部。
  3. 请求头(Headers)
    • 设置了 Accept: test/html,这告诉服务器客户端希望接受的响应类型是 test/html
  4. 请求参数(Parameters)
    • 设置了一个查询参数 key=value。这将会自动附加到 URL 后面,例如:https://httpbin.org/get?key=value
  5. 输出响应结果
    • 请求发送完毕后,返回的响应文本会通过 r.text 输出到控制台。

“无序参数” 解释:

在 CPR 库中,参数的顺序不重要,这意味着你可以传递 AuthenticationHeadersParameters 等参数的顺序是无关紧要的。你可以任意组合它们,CPR 库会自动处理这些参数。
例如,你可以按如下顺序传递参数:

auto r = cpr::Get(Headers{{"Accept", "test/html"}}, Parameters{{"key", "value"}}, Authentication{"user", "pass"}, Url{"https://httpbin.org/get"}
);

这两种写法的效果是一样的,都是发送一个包含身份验证、请求头和请求参数的 GET 请求。

中文总结:

这段代码演示了如何使用 CPR 库 发送一个 GET 请求,包含以下几个部分:

  • 身份验证Authentication)。
  • 请求头Headers)。
  • 请求参数Parameters)。
    需要注意的是,参数的顺序是 无关紧要 的,因此你可以自由地调整它们的顺序。

小贴士:

  • 在实际应用中,Authentication 通常用于需要授权的 API 请求。
  • HeadersParameters 是常见的设置请求细节的方式。请求头用于告知服务器期望的响应格式,参数则通常用于查询条件的传递。

这段代码使用 CPR 库发送一个 GET 请求,并演示了 CPR 支持的“无序参数”特性。这意味着你可以传递请求的参数(如 UrlHeadersAuthenticationParameters)的顺序不影响请求的构建。

代码解析:

#include <cpr.h>  // 引入CPR库头文件
#include <iostream>  // 引入输入输出流头文件
int main(int argc, char** argv) {// 发送一个GET请求到 https://httpbin.org/getauto r = cpr::Get(Url{"https://httpbin.org/get"},  // 请求的URLHeaders{{"Accept", "test/html"}},  // 请求头,表明希望接收 "test/html" 格式的响应Authentication{"user", "pass"},  // 使用用户名和密码进行身份验证Parameters{{"key", "value"}});  // 查询参数:key=value// 打印返回的响应文本std::cout << r.text << std::endl;
}

代码的具体功能:

  1. 发送 GET 请求
    • 代码发送了一个 GET 请求,请求的 URL 是 https://httpbin.org/get。这个地址是 httpbin 提供的一个用于测试 HTTP 请求的 API。
  2. 请求头(Headers)
    • 使用 Headers{{"Accept", "test/html"}} 设置了一个请求头,指定希望接收的响应格式为 "test/html"。这意味着服务器返回的内容应该符合 test/html 格式。
  3. 身份验证(Authentication)
    • Authentication{"user", "pass"} 提供了一个简单的基本认证,使用 "user" 作为用户名,"pass" 作为密码。这个请求会向服务器发送 Authorization 头,服务器会根据这些信息进行身份验证。
  4. 查询参数(Parameters)
    • Parameters{{"key", "value"}} 添加了一个查询参数 key=value,这意味着请求会变成 https://httpbin.org/get?key=value。服务器会根据这个参数处理请求。
  5. 输出响应
    • 发送请求后,响应的内容通过 r.text 打印到控制台。这是服务器返回的内容。

“无序参数” 说明:

在这段代码中,尽管参数的顺序是不同的,但 CPR 库能够正确地解析它们。也就是说,UrlHeadersAuthenticationParameters 的顺序不会影响请求的构造。这种特性叫做 “无序参数”,你可以按照任何顺序传递这些参数,库会处理它们。
例如,以下两种代码写法是等效的:

// 第一种顺序
auto r = cpr::Get(Url{"https://httpbin.org/get"}, Headers{{"Accept", "test/html"}}, Authentication{"user", "pass"}, Parameters{{"key", "value"}});
// 第二种顺序
auto r = cpr::Get(Parameters{{"key", "value"}}, Authentication{"user", "pass"}, Url{"https://httpbin.org/get"}, Headers{{"Accept", "test/html"}});

这两种方式都会产生相同的请求,只是参数的传递顺序不同,结果是一样的。

中文总结:

这段代码展示了如何使用 CPR 库 发送一个带有多个组成部分的 GET 请求

  • 请求 URL:https://httpbin.org/get
  • 请求头:Accept: test/html,表示希望接收 test/html 格式的响应。
  • 身份验证:通过用户名 "user" 和密码 "pass" 进行基本认证。
  • 请求参数:包含一个查询参数 key=value
    无序参数 特性说明:传递这些参数的顺序不影响请求的效果,CPR 库会自动正确解析。

这两段代码几乎完全相同,它们都展示了如何使用 CPR 库发送一个 GET 请求,并且都展示了 无序参数 的特性。也就是说,无论你传递参数的顺序如何,最终的请求都会是一样的。

代码解析:

第一段代码:
#include <cpr.h>  // 包含 CPR 库头文件
#include <iostream>  // 包含输入输出流头文件
int main(int argc, char** argv) {// 发送 GET 请求到 https://httpbin.org/getauto r = cpr::Get(Url{"https://httpbin.org/get"},  // 请求的 URLHeaders{{"Accept", "test/html"}},  // 请求头,表明希望接收 test/html 格式的响应Parameters{{"key", "value"}},  // 查询参数:key=valueAuthentication{"user", "pass"});  // 基本认证:用户名=user,密码=pass// 打印返回的响应文本std::cout << r.text << std::endl;
}
第二段代码:
#include <cpr.h>  // 包含 CPR 库头文件
#include <iostream>  // 包含输入输出流头文件
int main(int argc, char** argv) {// 发送 GET 请求到 https://httpbin.org/getauto r = cpr::Get(Url{"https://httpbin.org/get"},  // 请求的 URLAuthentication{"user", "pass"},  // 基本认证:用户名=user,密码=passParameters{{"key", "value"}},  // 查询参数:key=valueHeaders{{"Accept", "test/html"}});  // 请求头,表明希望接收 test/html 格式的响应// 打印返回的响应文本std::cout << r.text << std::endl;
}

主要区别:

  • 第一段代码 中,传递参数的顺序是:Url -> Headers -> Parameters -> Authentication
  • 第二段代码 中,传递参数的顺序是:Url -> Authentication -> Parameters -> Headers

无序参数特性:

CPR 库的一个重要特点就是 无序参数:也就是说,尽管参数的顺序不同,CPR 会自动处理这些参数,最终构造出相同的 HTTP 请求。

代码的功能:

  1. 发送 GET 请求
    • 无论顺序如何,最终的请求都会是发送到 https://httpbin.org/get 的 GET 请求。
  2. 请求头(Headers)
    • Headers{{"Accept", "test/html"}} 表示请求头中加入 Accept: test/html,告知服务器客户端希望接收 test/html 格式的响应。
  3. 请求参数(Parameters)
    • Parameters{{"key", "value"}} 表示请求中带有查询参数 key=value,这个参数会附加到 URL 后面,最终请求会是 https://httpbin.org/get?key=value
  4. 身份验证(Authentication)
    • Authentication{"user", "pass"} 表示基本认证,其中 user 是用户名,pass 是密码。这个参数会被处理为 Authorization 头并加到请求中。
  5. 输出响应
    • 请求发出后,响应的文本会通过 r.text 输出到控制台。

中文总结:

这两段代码完全等效,只是 参数的顺序不同。由于 CPR 库支持“无序参数”的特性,你可以任意调整 UrlHeadersParametersAuthentication 的顺序。最终,服务器接收到的请求是一样的。

  • 无论参数顺序如何变化,生成的请求内容不会改变,这使得你在使用 CPR 库时更加灵活,可以根据需要调整参数顺序,而不必担心顺序错误。

这段代码演示了如何使用 CPR 库中的 Session 对象来发送 HTTP 请求。Session 类用于管理多次请求的设置,避免每次发送请求时都重复设置相同的参数。它允许你在一个会话中持久化设置(例如 URL、请求头、参数等),然后多次调用。

代码解析:

#include <cpr.h>  // 包含 CPR 库头文件
#include <iostream>  // 包含输入输出流头文件
int main(int argc, char** argv) {// 创建一个 Session 对象Session session;// 设置 Session 对象的请求 URLsession.SetUrl("https://httpbin.org/get");// 设置 Session 对象的查询参数session.SetParameters({{"key", "value"}});// 发送 GET 请求auto r = session.Get();// 打印响应文本std::cout << r.text << std::endl;
}

代码的功能:

  1. 创建一个 Session 对象
    • Session session; 创建了一个 Session 对象。该对象用于持久化请求的一些设置,例如 URL 和参数等。
  2. 设置 URL
    • session.SetUrl("https://httpbin.org/get"); 设置了请求的 URL。在这个例子中,URL 是 https://httpbin.org/get,这是一个可以用来测试 HTTP 请求的公共 API。
  3. 设置查询参数
    • session.SetParameters({{"key", "value"}}); 设置了一个查询参数 key=value,这个参数会附加到 URL 上,构成最终的请求 URL:https://httpbin.org/get?key=value
  4. 发送 GET 请求
    • auto r = session.Get(); 通过 session.Get() 发送 GET 请求。Get() 方法会使用在 session 对象中设置的 URL 和查询参数来构建请求,并发送到服务器。
  5. 输出响应内容
    • std::cout << r.text << std::endl; 打印服务器响应的文本内容。r.text 存储了服务器返回的响应数据。

关键点:

  • Session 对象:通过 Session 对象,你可以在会话期间共享一些设置(如 URL 和查询参数)。这样,你就不需要每次发送请求时都重复设置相同的内容。
  • 参数持久化SetUrl()SetParameters() 设置的内容在整个会话期间有效。你可以发送多个请求,并保持之前设置的参数和 URL。

示例说明:

这段代码相当于每次发送请求时都设置了 URL 和查询参数,使用了 Session 对象来简化代码。通过 session.Get(),你发送了一个带有查询参数 key=value 的 GET 请求,返回的响应会显示在控制台。
例如,URL 会是 https://httpbin.org/get?key=value,服务器会返回相应的内容。

中文总结:

通过使用 Session 对象,代码可以在同一个会话中发送多个请求,并且能够持久化请求设置(例如 URL 和参数),避免每次都重复设置。这对于需要多次发送类似请求的情况非常方便。

  • Session 可以管理请求的状态和设置,提高代码的可复用性。
  • SetUrl() 设置请求的 URL。
  • SetParameters() 设置查询参数。

这段代码展示了如何使用 CPR 库的异步请求功能来并发发送多个 HTTP GET 请求。通过 std::futurestd::async,我们可以在不阻塞主线程的情况下发送多个请求,并在稍后获取每个请求的响应。这种方式可以有效地提高程序的性能,尤其是在需要同时发送大量请求时。

代码解析:

#include <cpr.h>  // 包含 CPR 库头文件
#include <iostream>  // 包含输入输出流头文件
#include <future>  // 包含未来(future)头文件,用于异步操作
#include <vector>  // 包含向量(vector)头文件,用于存储响应对象
int main(int argc, char** argv) {std::vector<std::future<Response>> responses;  // 用于存储异步响应的容器auto url = Url{"https://httpbin.org/get"};  // 请求的 URL// 循环发送 1000 个异步 GET 请求for (int i = 0; i < 1000; ++i) {// 使用 GetAsync 方法异步发送 GET 请求,结果保存在 future 中responses.emplace_back(cpr::GetAsync(url));  }// 等待所有异步请求完成,并输出响应内容for (auto& r : responses) {// 获取 future 对象的值(即 GET 请求的响应),并打印响应文本std::cout << r.get().text << std::endl;}
}

代码的具体功能:

  1. 异步请求
    • cpr::GetAsync(url)CPR 库 提供的异步 GET 请求方法。与常规的同步请求不同,异步请求不会立即阻塞程序,而是通过返回一个 std::future<Response> 对象,让你在稍后获取请求的结果。
  2. 存储响应对象
    • std::vector<std::future<Response>> responses 用来存储所有异步请求的 std::future 对象。每个 std::future 对象表示一个异步操作的未来结果,你可以通过 r.get() 获取请求的响应。
  3. 并发发送请求
    • for 循环中,cpr::GetAsync(url) 被调用 1000 次,每次调用都会向 responses 向量中添加一个新的 future 对象。这样,1000 个异步 GET 请求会几乎同时开始,程序不会因为一个请求的等待而停下来。
  4. 等待所有请求完成并获取结果
    • 在第二个 for 循环中,通过 r.get() 获取每个异步请求的结果。r.get() 会阻塞当前线程,直到相应的 GET 请求完成并返回结果,然后将其响应的 text(即服务器返回的响应内容)打印到控制台。

异步请求的优势:

  • 提高效率:异步请求不会阻塞主线程,因此可以同时发起多个请求而不会等待每个请求单独完成。对于需要发送大量请求的场景(如批量请求数据或测试 API),可以显著提升程序的运行效率。
  • 非阻塞:当调用 cpr::GetAsync() 时,程序不会等待请求完成,而是继续执行后续的代码。这意味着你可以在等待请求的过程中执行其他操作,而不是每次都阻塞直到请求返回。

工作原理:

  1. 每次调用 cpr::GetAsync(url) 时,它启动一个新的异步请求,并将返回的 future 对象存储在 responses 向量中。
  2. 异步请求并不会阻塞主线程,程序会继续执行并发发送更多的请求。
  3. 当所有请求都发出后,主线程等待每个 future 对象完成,并通过 r.get() 获取每个请求的响应结果。
  4. 最后,将每个请求的响应打印到控制台。

代码输出:

代码会打印出 1000 个请求的响应内容,这些内容是从 https://httpbin.org/get 获取的 JSON 格式的响应。具体的输出内容会根据请求的具体响应不同而有所不同。

中文总结:

这段代码展示了如何利用 CPR 库std::future 进行 异步请求。通过并发发送大量 HTTP GET 请求,程序在不阻塞主线程的情况下等待所有请求完成,最终打印出每个请求的响应内容。
异步请求的优点

  • 可以并发发送多个请求而不等待每个请求完成,适合大规模并发请求。
  • 使用 std::future 获取异步操作的结果,等待所有请求的完成并处理结果。

这段代码展示了如何使用 CPR 库 发送 异步回调请求。在这个例子中,cpr::GetCallback 被用来发送一个 GET 请求,并在请求完成后通过回调函数处理响应数据。与使用 std::future 的异步请求不同,这种方法采用 回调 函数来处理请求的响应。

代码解析:

#include <cpr.h>  // 包含 CPR 库头文件
#include <iostream>  // 包含输入输出流头文件
int main(int argc, char** argv) {// 发送异步 GET 请求,并使用回调函数处理响应auto future = cpr::GetCallback([](Response r) { return r.text;  // 回调函数将返回响应的文本内容}, Url{"https://httpbin.org/get"});  // 请求的 URL// 获取并输出回调函数返回的响应内容std::cout << future.get() << std::endl;  // 获取 future 的结果并打印
}

代码的功能:

  1. 异步回调请求
    • cpr::GetCallback 方法用于发送一个异步 GET 请求,并且允许你通过回调函数处理响应。这个方法会立即返回一个 std::future 对象,表示异步操作的结果。这个 future 对象可以在稍后获取请求的结果。
  2. 回调函数
    • cpr::GetCallback 中,传入了一个回调函数 [](Response r) { return r.text; }。当请求完成时,CPR 会调用这个回调函数,并将服务器的响应(即 Response 对象)传递给它。回调函数从 Response 对象中提取出 text(即响应的内容)并返回。
  3. 获取异步结果
    • auto future = cpr::GetCallback(...); 会立即返回一个 std::future 对象。这个对象代表了异步请求的结果,可以通过 future.get() 来获取异步请求的结果。get() 会阻塞当前线程,直到请求完成,并且返回回调函数的结果。
  4. 打印响应内容
    • std::cout << future.get() << std::endl; 会等待 future 完成并获取回调函数返回的结果(即响应的文本内容),然后将其打印到控制台。

异步回调的优点:

  • 非阻塞请求cpr::GetCallback 允许你在请求发出的同时继续执行其他任务,直到请求完成后再通过回调处理响应。
  • 简洁的回调机制:回调函数在请求完成后自动调用,处理响应的方式更加灵活。
  • 自动处理响应:不需要手动检查请求是否完成,CPR 会在请求完成后自动调用回调函数。

工作流程:

  1. 调用 cpr::GetCallback 发送异步请求。
  2. 请求发出后,程序继续执行,不会被请求的等待过程阻塞。
  3. 一旦请求完成,Response 对象会传递给回调函数,回调函数会提取 r.text 并返回。
  4. future.get() 等待回调函数完成,获取异步请求的结果(即响应内容)并打印。

输出:

代码将输出 https://httpbin.org/get 的响应内容,这通常是一个包含请求的 JSON 数据的响应。具体的内容可能类似于:

{"args": {},"headers": {"Accept": "test/html","Content-Length": "0","Host": "httpbin.org","User-Agent": "cpr/1.0.0"},"origin": "123.45.67.89","url": "https://httpbin.org/get"
}

中文总结:

这段代码展示了如何使用 CPR 库异步回调请求。它通过 cpr::GetCallback 发送一个异步 GET 请求,并在请求完成后通过回调函数来处理服务器的响应。
异步回调的工作原理

  • 发送请求cpr::GetCallback 发送异步请求,传入一个回调函数来处理响应。
  • 回调函数:请求完成后,回调函数会被调用,并处理 Response 对象(例如提取响应的文本)。
  • 返回结果:通过 future.get() 获取回调函数返回的结果,并打印响应内容。
    这种方式的优点在于它采用了 异步回调 的方式,使得代码更为简洁和高效,避免了阻塞等待响应的过程。

这段代码展示了如何使用 CPR 库发送一个 GET 请求,并打印出响应的文本内容。它是最基础的请求示例。

代码解析:

#include <cpr.h>  // 引入 CPR 库,提供 HTTP 请求功能
#include <iostream>  // 引入输入输出流,用于输出结果到控制台
int main(int argc, char** argv) {// 发送 GET 请求到 https://httpbin.org/getauto r = cpr::Get(Url{"https://httpbin.org/get"});  // 输出响应的文本内容std::cout << r.text << std::endl;  
}

代码功能:

  1. 发送 GET 请求
    • cpr::Get(Url{"https://httpbin.org/get"}) 通过 CPR 库向指定的 URL(https://httpbin.org/get)发送一个 GET 请求。该 URL 是一个公开的 API,用于测试 HTTP 请求。
  2. 返回响应
    • cpr::Get 函数会返回一个 Response 对象,包含了服务器对请求的响应信息。我们可以通过 r.text 获取响应体的文本内容。
  3. 输出响应内容
    • std::cout << r.text << std::endl; 将获取到的响应文本输出到控制台。

代码输出:

  • 当你运行这段代码时,程序会向 https://httpbin.org/get 发送 GET 请求,然后打印出响应内容。返回的内容通常是一个包含请求信息的 JSON 数据。例如,响应可能如下所示:
{"args": {},"headers": {"Accept": "test/html","Content-Length": "0","Host": "httpbin.org","User-Agent": "cpr/1.0.0"},"origin": "123.45.67.89","url": "https://httpbin.org/get"
}

这里的 JSON 内容包含了请求的一些元数据(如请求头、IP 地址、请求的 URL 等)。

中文总结:

这段代码演示了使用 CPR 库 发送一个 简单的 GET 请求,并输出响应的内容。GET 请求 是一种常见的 HTTP 请求方式,通常用于获取服务器上的资源。

  • cpr::Get 发送 GET 请求。
  • r.text 获取响应体的文本内容。
  • std::cout 输出响应到控制台。
    HTTP 中,GETsession 是两个不同的概念,它们通常会在客户端与服务器之间的通信中一起使用,但它们有不同的含义和用途。让我们分别解释它们:

1. GET(HTTP 请求方法)

  • 定义GET 是 HTTP 协议中的一种请求方法,用于从服务器请求获取资源。
  • 用途GET 请求用于请求数据或资源。它是最常见的 HTTP 请求方法之一,通常用于加载网页、获取 API 数据等。
  • 特点
    • GET 请求通常是无状态的,即每次请求都相互独立,服务器不会保存任何前一次请求的状态。
    • 请求的数据通常通过 URL 或查询参数传递(如:https://example.com/api?user=abc)。
    • GET 请求不能在请求体中传递数据,数据是通过 URL 的查询参数传递的。
    • 由于是无状态的,GET 请求适用于访问公共资源或不需要修改服务器端数据的场景。

2. Session(会话)

  • 定义Session 是服务器端为每个用户生成的一个会话信息,用于跟踪用户在多个请求之间的状态。
  • 用途:会话用于在多个 HTTP 请求之间维持用户的状态,比如用户登录后的状态、购物车信息等。由于 HTTP 是无状态的协议(即每次请求都是独立的),session 用来解决这一问题,使得服务器能够在多个请求之间“记住”用户的状态。
  • 特点
    • 会话信息通常存储在服务器端,而客户端只会持有一个标识符,通常是通过 cookie 来传递这个标识符。
    • session 可以在多个请求之间持续,通常在用户访问网站或应用时保持。
    • 一般情况下,服务器在客户端首次访问时创建会话,并为会话生成唯一的 ID(比如 session ID)。此 ID 会通过 cookie 或 URL 参数返回给客户端,后续的请求会附带该 ID,从而能够找到对应的会话信息。
    • 会话用于跟踪用户的登录状态、用户行为、购物车、用户偏好设置等。

区别总结:

特性GETSession
定义HTTP 请求方法,用于请求数据或资源服务器端存储的用户状态信息,用于跨多个请求之间保持会话状态
用途请求并获取资源存储并管理用户的状态,如登录状态、购物车等
数据存储位置数据在 URL 中传递(查询参数)存储在服务器端,客户端只持有 session ID
状态无状态(每次请求独立)有状态(保持跨请求的会话信息)
持久性单次请求,刷新或关闭页面会丢失会话信息保持在多个请求之间,通常由浏览器保持
常用场景获取网页或 API 数据用户登录、购物车、偏好设置等

举个例子:

1. GET 请求示例
#include <cpr.h>
#include <iostream>
int main() {auto r = cpr::Get(cpr::Url{"https://httpbin.org/get"});std::cout << r.text << std::endl;
}
  • 这里,GET 请求用来从 httpbin.org 获取数据。每个 GET 请求都是独立的,不会保持用户的状态。
2. 使用 Session 示例
#include <cpr.h>
#include <iostream>
int main() {cpr::Session session;// 设置用户身份信息(如登录信息)session.SetAuth("username", "password");// 发送一个 GET 请求,带着会话信息auto r = session.Get(cpr::Url{"https://httpbin.org/get"});std::cout << r.text << std::endl;
}
  • 在这个例子中,我们使用了 cpr::Session 来模拟用户会话。在第一次请求时,session 会为这个用户生成一个会话标识符,并在后续请求中附带这个标识符,从而在多个请求之间维持用户的登录状态。

什么时候使用 GET 和 Session:

  • GET 请求适用于获取资源,如页面、图片、JSON 数据等。
  • Session 适用于需要在多个请求之间维持状态的场景,如用户登录、购物车、游戏进度等。
    总结来说,GET 是一种 HTTP 请求方法,用于请求资源,而 Session 是服务器端管理用户状态的机制,它可以用于多个请求之间共享数据。两者经常结合使用,比如用户登录时,通过 Session 跟踪用户的身份,而通过 GET 请求获取资源。
http://www.xdnf.cn/news/13395.html

相关文章:

  • Vim 插件管理:MiniBufExplorer 使用指南
  • 区块链Web3项目的开发
  • Dify 知识库深度剖析:从构建到高效应用
  • 【大模型RAG】拍照搜题技术架构速览:三层管道、两级检索、兜底大模型
  • kotlin kmp 副作用函数 effect
  • 使用Ajax从前端向后端发起请求
  • Prometheus基础使用指南
  • 鹰盾加密虚拟机保护技术的深度解析:从指令级虚拟化到动态对抗系统
  • (LeetCode 每日一题) 3442. 奇偶频次间的最大差值 I (哈希、字符串)
  • Windows cmd中文乱码解决方法(Windows控制台中文乱码、CMD乱码、控制台乱码、Command Prompt命令提示符cmd.exe乱码)
  • JxBrowser 7.43.2 版本发布啦!
  • 预训练模型 CBAM注意力
  • 【docker n8n】windows环境如何挂载
  • 【计算机组成原理 第5版】白、戴编著 第四章 指令系统 课后题总结
  • 第二章 开发板与芯片介绍
  • 慢接口优化万能公式-适合所有系统
  • 【论文阅读笔记】HaDes幻觉检测benchmark
  • GISBox如何导入Revit格式的BIM数据?
  • 案例解读:交安与建安安全员 C 证在实践中的差异
  • 电路图识图基础知识-电机顺序启动控制电路解析(二十二)
  • 期末考试复习总结-《从简单的页面开始(下)》
  • NLP学习路线图(三十八): 文本摘要
  • 3分钟配置好nacos集群(docker compose)
  • 接口测试与接口测试面试题
  • 讲讲JVM的垃圾回收机制
  • 【八股消消乐】构建微服务架构体系—熔断恢复抖动优化
  • 认识 Python 【适合0基础】
  • 魔兽世界正式服插件与宏-敏锐盗贼实用宏探索(3)-起手奥义【袭】之突如其来
  • C++ Programming Language —— 第1章:核心语法
  • SpringBoot自动化部署实战