From ad1016734e2ab8885f2fefe939cfc385a1b1c844 Mon Sep 17 00:00:00 2001 From: Chunting Gu Date: Mon, 26 Aug 2019 12:13:25 +0800 Subject: [PATCH] Rename Request() to Send(). --- README.md | 103 ++++++++++++++------------- README_zh_CN.md | 102 ++++++++++++--------------- autotest/client_autotest.cc | 130 +++++++++++++++-------------------- examples/client_basics.cc | 26 ++++--- examples/file_downloader.cc | 3 +- examples/form_client.cc | 9 ++- examples/github_client.cc | 29 ++++---- examples/rest_book_client.cc | 18 ++--- webcc/client_session.cc | 6 +- webcc/client_session.h | 4 +- 10 files changed, 195 insertions(+), 235 deletions(-) diff --git a/README.md b/README.md index 8812f9a..355944c 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ Lightweight C++ HTTP client and server library based on [Boost Asio](https://www.boost.org/doc/libs/release/libs/asio/). -Please turn to our [Wiki](https://github.com/sprinfall/webcc/wiki) (under construction) for more tutorials and guides. +Please turn to our [Wiki](https://github.com/sprinfall/webcc/wiki) for more tutorials and guides. Wondering how to build Webcc? Check [Build Instructions](https://github.com/sprinfall/webcc/wiki/Build-Instructions). @@ -12,7 +12,7 @@ Git repo: https://github.com/sprinfall/webcc. Please check this one instead of t **Features** -- Cross-platform: Linux, Windows and Mac +- Cross-platform: Windows, Linux and MacOS - Easy-to-use client API inspired by Python [requests](https://2.python-requests.org//en/master/) - SSL/HTTPS support with OpenSSL (optional) - GZip compression support with Zlib (optional) @@ -25,7 +25,6 @@ Git repo: https://github.com/sprinfall/webcc. Please check this one instead of t - Source code follows [Google C++ Style](https://google.github.io/styleguide/cppguide.html) - Automation tests and unit tests included - No memory leak detected by [VLD](https://kinddragon.github.io/vld/) -- etc. ## Client API @@ -48,7 +47,9 @@ int main() { // Catch exceptions for error handling. try { // Send a HTTP GET request. - auto r = session.Get("http://httpbin.org/get"); + auto r = session.Send(webcc::RequestBuilder{}. + Get("http://httpbin.org/get") + ()); // Print the response data. std::cout << r->data() << std::endl; @@ -61,46 +62,30 @@ int main() { } ``` -The `Get()` method is nothing but a shortcut of `Request()`. Using `Request()` directly is more complicated: - -```cpp -auto r = session.Request(webcc::RequestBuilder{}.Get("http://httpbin.org/get")()); -``` - As you can see, a helper class named `RequestBuilder` is used to chain the parameters and finally build a request object. Please pay attention to the `()` operator. -Both the shortcut and `Request()` accept URL query parameters: +URL query parameters can be easily added through `Query()` method: ```cpp -// Query parameters are passed using a std::vector. -session.Get("http://httpbin.org/get", { "key1", "value1", "key2", "value2" }); - -session.Request(webcc::RequestBuilder{}. - Get("http://httpbin.org/get"). - Query("key1", "value1"). - Query("key2", "value2") - ()); +session.Send(webcc::RequestBuilder{}. + Get("http://httpbin.org/get"). + Query("key1", "value1").Query("key2", "value2") + ()); ``` Adding additional headers is also easy: ```cpp -session.Get("http://httpbin.org/get", - {"key1", "value1", "key2", "value2"}, - {"Accept", "application/json"}); // Also a std::vector - -session.Request(webcc::RequestBuilder{}. - Get("http://httpbin.org/get"). - Query("key1", "value1"). - Query("key2", "value2"). - Header("Accept", "application/json") - ()); +session.Send(webcc::RequestBuilder{}. + Get("http://httpbin.org/get"). + Header("Accept", "application/json") + ()); ``` Accessing HTTPS has no difference from HTTP: ```cpp -session.Get("https://httpbin.org/get"); +session.Send(webcc::RequestBuilder{}.Get("https://httpbin.org/get")()); ``` *NOTE: The HTTPS/SSL support requires the build option `WEBCC_ENABLE_SSL` to be enabled.* @@ -108,38 +93,40 @@ session.Get("https://httpbin.org/get"); Listing GitHub public events is not a big deal: ```cpp -auto r = session.Get("https://api.github.com/events"); +auto r = session.Send(webcc::RequestBuilder{}. + Get("https://api.github.com/events") + ()); ``` You can then parse `r->data()` to JSON object with your favorite JSON library. My choice for the examples is [jsoncpp](https://github.com/open-source-parsers/jsoncpp). But Webcc itself doesn't understand JSON nor require one. It's up to you to choose the most appropriate JSON library. -The shortcuts (`Get()`, `Post()`, etc.) are easier to use but `RequestBuilder` is more powerful. It provides a lot of functions for you to customize the request. Let's see more examples. +`RequestBuilder` provides a lot of functions for you to customize the request. Let's see more examples. In order to list the followers of an authorized GitHub user, you need either **Basic Authorization**: ```cpp -session.Request(webcc::RequestBuilder{}. - Get("https://api.github.com/user/followers"). - AuthBasic(login, password) // Should be replaced by real login and password - ()); +session.Send(webcc::RequestBuilder{}. + Get("https://api.github.com/user/followers"). + AuthBasic(login, password) // Should be replaced by valid login and passwords + ()); ``` Or **Token Authorization**: ```cpp -session.Request(webcc::RequestBuilder{}. - Get("https://api.github.com/user/followers"). - AuthToken(token) // Should be replaced by a valid token - ()); +session.Send(webcc::RequestBuilder{}. + Get("https://api.github.com/user/followers"). + AuthToken(token) // Should be replaced by a valid token + ()); ``` Though **Keep-Alive** (i.e., persistent connection) is a good feature and enabled by default, you can turn it off: ```cpp -auto r = session.Request(webcc::RequestBuilder{}. - Get("http://httpbin.org/get"). - KeepAlive(false) // No Keep-Alive - ()); +auto r = session.Send(webcc::RequestBuilder{}. + Get("http://httpbin.org/get"). + KeepAlive(false) // No Keep-Alive + ()); ``` The API for other HTTP requests is no different from GET. @@ -147,24 +134,36 @@ The API for other HTTP requests is no different from GET. POST request needs a body which is normally a JSON string for REST API. Let's post a small UTF-8 encoded JSON string: ```cpp -session.Request(webcc::RequestBuilder{}. - Post("http://httpbin.org/post"). - Body("{'name'='Adam', 'age'=20}"). - Json().Utf8() - ()); +session.Send(webcc::RequestBuilder{}. + Post("http://httpbin.org/post"). + Body("{'name'='Adam', 'age'=20}").Json().Utf8() + ()); ``` Webcc has the ability to stream large response data to a file. This is especially useful when downloading files. ```cpp -auto r = session.Request(webcc::RequestBuilder{}. - Get("http://httpbin.org/image/jpeg")(), - true); // !!! +auto r = session.Send(webcc::RequestBuilder{}. + Get("http://httpbin.org/image/jpeg") + (), true); // stream = true // Move the streamed file to your destination. r->file_body()->Move("./wolf.jpeg"); ``` +Streaming is also available for uploading: + +```cpp +auto r = session.Send(webcc::RequestBuilder{}. + Post("http://httpbin.org/post"). + File(path) // Should be replaced by a valid file path + ()); +``` + +The file will not be loaded into the memory all at once, instead, it will be read and sent piece by piece. + +Please note that `Content-Length` header will still be set to the true size of the file, this is different from the handling of chunked data (`Transfer-Encoding: chunked`). + Please check the [examples](https://github.com/sprinfall/webcc/tree/master/examples/) for more information. ## Server API diff --git a/README_zh_CN.md b/README_zh_CN.md index bef7030..79c0244 100644 --- a/README_zh_CN.md +++ b/README_zh_CN.md @@ -41,7 +41,9 @@ int main() { try { // 发起一个 HTTP GET 请求 - auto r = session.Get("http://httpbin.org/get"); + auto r = session.Send(webcc::RequestBuilder{}. + Get("http://httpbin.org/get") + ()); // 输出响应数据 std::cout << r->data() << std::endl; @@ -55,47 +57,30 @@ int main() { } ``` -因为 `Get()` 不过是 `Request()` 的一种快捷方式,直接调用 `Request()` 会更复杂一些: +如你所见,这里通过一个辅助类 `RequestBuilder`,串联起各种参数,最后再生成一个请求对象。注意不要漏了最后的 `()` 操作符。 -```cpp -auto r = session.Request(webcc::RequestBuilder{}.Get("http://httpbin.org/get")()); -``` - -这里多了个辅助类 `RequestBuilder`,用来串联起各种参数,最后再生成一个请求对象。注意不要漏了 `()` 操作符。 - -不管是 `Get` 还是 `Request()`,都接受 URL 查询参数: +通过 `Query()` 可以方便地指定 URL 查询参数: ```cpp -// 查询参数由 std::vector 一起指定,键值成对出现 -session.Get("http://httpbin.org/get", { "key1", "value1", "key2", "value2" }); - -// 查询参数由 Query() 挨个指定 -session.Request(webcc::RequestBuilder{}. - Get("http://httpbin.org/get"). - Query("key1", "value1"). - Query("key2", "value2") - ()); +session.Send(webcc::RequestBuilder{}. + Get("http://httpbin.org/get"). + Query("key1", "value1").Query("key2", "value2") + ()); ``` 要添加额外的头部也很简单: ```cpp -session.Get("http://httpbin.org/get", - {"key1", "value1", "key2", "value2"}, - {"Accept", "application/json"}); // 也是 std::vector - -session.Request(webcc::RequestBuilder{}. - Get("http://httpbin.org/get"). - Query("key1", "value1"). - Query("key2", "value2"). - Header("Accept", "application/json") - ()); +session.Send(webcc::RequestBuilder{}. + Get("http://httpbin.org/get"). + Header("Accept", "application/json") + ()); ``` 访问 HTTPS 和访问 HTTP 没有差别,对用户是透明的: ```cpp -session.Get("https://httpbin.org/get"); +session.Send(webcc::RequestBuilder{}.Get("https://httpbin.org/get")()); ``` *注意:对 HTTPS/SSL 的支持,需要启用编译选项 `WEBCC_ENABLE_SSL`,也会依赖 OpenSSL。* @@ -103,40 +88,42 @@ session.Get("https://httpbin.org/get"); 列出 GitHub 公开事件 (public events) 也不是什么难题: ```cpp -auto r = session.Get("https://api.github.com/events"); +auto r = session.Send(webcc::RequestBuilder{}. + Get("https://api.github.com/events") + ()); ``` 然后,你可以把 `r->data()` 解析成 JSON 对象,随便用个什么 JSON 程序库。 我在示例程序里用的是 [jsoncpp](https://github.com/open-source-parsers/jsoncpp),但是 Webcc 本身并不理解 JSON,用什么 JSON 程序库,完全是你自己的选择。 -快捷函数(`Get()`,`Post()`,等)用起来方便,但是参数有限,限制比较多。`RequestBuilder` 更灵活更强大,它提供了很多函数供你定制请求的样子。 +`RequestBuilder` 本质上是为了解决 C++ 没有“键值参数”的问题,它提供了很多函数供你定制请求的样子。 -为了列出一个授权的 (authorized) GitHub 用户的“粉丝” (followers),要么使用 **Basic 认证**: +为了列出一个授权的 (authorized) GitHub 用户的“粉丝” (followers),要么使用 **Basic 认证**: ```cpp -session.Request(webcc::RequestBuilder{}. - Get("https://api.github.com/user/followers"). - AuthBasic(login, password) // 应该替换成具体的账号、密码 - ()); +session.Send(webcc::RequestBuilder{}. + Get("https://api.github.com/user/followers"). + AuthBasic(login, password) // 应该替换成具体的账号、密码 + ()); ``` 要么使用 **Token 认证**: ```cpp -session.Request(webcc::RequestBuilder{}. - Get("https://api.github.com/user/followers"). - AuthToken(token) // 应该替换成具体合法的 token - ()); +session.Send(webcc::RequestBuilder{}. + Get("https://api.github.com/user/followers"). + AuthToken(token) // 应该替换成具体合法的 token + ()); ``` -尽管**持久连接** (Keep-Alive) 这个功能不错,你也可以手动关掉它: +尽管 **持久连接** (Keep-Alive) 这个功能不错,你也可以手动关掉它: ```cpp -auto r = session.Request(webcc::RequestBuilder{}. - Get("http://httpbin.org/get"). - KeepAlive(false) // 不要 Keep-Alive - ()); +auto r = session.Send(webcc::RequestBuilder{}. + Get("http://httpbin.org/get"). + KeepAlive(false) // 不要 Keep-Alive + ()); ``` 其他 HTTP 请求的 API 跟 GET 并无太多差别。 @@ -144,19 +131,18 @@ auto r = session.Request(webcc::RequestBuilder{}. POST 请求需要一个“体” (body),就 REST API 来说通常是一个 JSON 字符串。让我们 POST 一个 UTF-8 编码的 JSON 字符串: ```cpp -session.Request(webcc::RequestBuilder{}. - Post("http://httpbin.org/post"). - Body("{'name'='Adam', 'age'=20}"). - Json().Utf8() - ()); +session.Send(webcc::RequestBuilder{}. + Post("http://httpbin.org/post"). + Body("{'name'='Adam', 'age'=20}").Json().Utf8() + ()); ``` Webcc 可以把大型的响应数据串流到临时文件,串流在下载文件时特别有用。 ```cpp -auto r = session.Request(webcc::RequestBuilder{}. - Get("http://httpbin.org/image/jpeg")(), - true); // stream = true +auto r = session.Send(webcc::RequestBuilder{}. + Get("http://httpbin.org/image/jpeg") + (), true); // stream = true // 把串流的文件移到目标位置 r->file_body()->Move("./wolf.jpeg"); @@ -165,13 +151,13 @@ r->file_body()->Move("./wolf.jpeg"); 不光下载,上传也可以串流: ```cpp -auto r = session.Request(webcc::RequestBuilder{}. - Post("http://httpbin.org/post"). - File(path) // 应该替换成具体的文件路径 - ()); +auto r = session.Send(webcc::RequestBuilder{}. + Post("http://httpbin.org/post"). + File(path) // 应该替换成具体的文件路径 + ()); ``` -这个文件在 POST 时,不会一次加载到内存,读一块数据发一块数据,直到发送完。 +这个文件在 POST 时,不会一次加载到内存,而是读一块数据发一块数据,直到发送完。 注意,`Content-Length` 头部还是会设置为文件的真实大小,不同于 `Transfer-Encoding: chunked` 的分块数据形式。 diff --git a/autotest/client_autotest.cc b/autotest/client_autotest.cc index d3c589b..fbed4c0 100644 --- a/autotest/client_autotest.cc +++ b/autotest/client_autotest.cc @@ -37,9 +37,9 @@ TEST(ClientTest, Head) { webcc::ClientSession session; try { - auto r = session.Request(webcc::RequestBuilder{}. - Head("http://httpbin.org/get") - ()); + auto r = session.Send(webcc::RequestBuilder{}. + Head("http://httpbin.org/get") + ()); EXPECT_EQ(webcc::Status::kOK, r->status()); EXPECT_EQ("OK", r->reason()); @@ -59,10 +59,10 @@ TEST(ClientTest, Head_AcceptEncodingIdentity) { webcc::ClientSession session; try { - auto r = session.Request(webcc::RequestBuilder{}. - Head("http://httpbin.org/get"). - Header("Accept-Encoding", "identity") - ()); + auto r = session.Send(webcc::RequestBuilder{}. + Head("http://httpbin.org/get"). + Header("Accept-Encoding", "identity") + ()); EXPECT_EQ(webcc::Status::kOK, r->status()); EXPECT_EQ("OK", r->reason()); @@ -106,12 +106,11 @@ TEST(ClientTest, Get) { webcc::ClientSession session; try { - auto r = session.Request(webcc::RequestBuilder{}. - Get("http://httpbin.org/get"). - Query("key1", "value1"). - Query("key2", "value2"). - Header("Accept", "application/json") - ()); + auto r = session.Send(webcc::RequestBuilder{}. + Get("http://httpbin.org/get"). + Query("key1", "value1").Query("key2", "value2"). + Header("Accept", "application/json") + ()); AssertGet(r); @@ -125,10 +124,9 @@ TEST(ClientTest, Get_QueryEncode) { webcc::ClientSession session; try { - auto r = session.Request(webcc::RequestBuilder{}. - Get("http://httpbin.org/get"). - Query("name", "Chunting Gu", true) - ()); + auto r = session.Send(webcc::RequestBuilder{}.Get("http://httpbin.org/get"). + Query("name", "Chunting Gu", true) + ()); EXPECT_EQ(webcc::Status::kOK, r->status()); EXPECT_EQ("OK", r->reason()); @@ -151,12 +149,11 @@ TEST(ClientTest, Get_SSL) { try { // HTTPS is auto-detected from the URL scheme. - auto r = session.Request(webcc::RequestBuilder{}. - Get("https://httpbin.org/get"). - Query("key1", "value1"). - Query("key2", "value2"). - Header("Accept", "application/json") - ()); + auto r = session.Send(webcc::RequestBuilder{}. + Get("https://httpbin.org/get"). + Query("key1", "value1").Query("key2", "value2"). + Header("Accept", "application/json") + ()); AssertGet(r); @@ -171,9 +168,9 @@ TEST(ClientTest, Get_Jpeg_NoStream) { webcc::ClientSession session; try { - auto r = session.Request(webcc::RequestBuilder{}. - Get("http://httpbin.org/image/jpeg") - ()); + auto r = session.Send(webcc::RequestBuilder{}. + Get("http://httpbin.org/image/jpeg") + ()); // TODO: Verify the response is a valid JPEG image. //std::ofstream ofs(, std::ios::binary); @@ -188,10 +185,9 @@ TEST(ClientTest, Get_Jpeg_Stream) { webcc::ClientSession session; try { - auto r = session.Request(webcc::RequestBuilder{}. - Get("http://httpbin.org/image/jpeg") - (), - true); + auto r = session.Send(webcc::RequestBuilder{}. + Get("http://httpbin.org/image/jpeg") + (), true); auto file_body = r->file_body(); @@ -227,10 +223,9 @@ TEST(ClientTest, Get_Jpeg_Stream_NoMove) { webcc::Path ori_path; { - auto r = session.Request(webcc::RequestBuilder{}. - Get("http://httpbin.org/image/jpeg") - (), - true); + auto r = session.Send(webcc::RequestBuilder{}. + Get("http://httpbin.org/image/jpeg") + (), true); auto file_body = r->file_body(); @@ -258,9 +253,9 @@ TEST(ClientTest, Get_Gzip) { webcc::ClientSession session; try { - auto r = session.Request(webcc::RequestBuilder{}. - Get("http://httpbin.org/gzip") - ()); + auto r = session.Send(webcc::RequestBuilder{}. + Get("http://httpbin.org/gzip") + ()); Json::Value json = StringToJson(r->data()); @@ -278,9 +273,9 @@ TEST(ClientTest, Get_Deflate) { webcc::ClientSession session; try { - auto r = session.Request(webcc::RequestBuilder{}. - Get("http://httpbin.org/deflate") - ()); + auto r = session.Send(webcc::RequestBuilder{}. + Get("http://httpbin.org/deflate") + ()); Json::Value json = StringToJson(r->data()); @@ -300,10 +295,9 @@ TEST(ClientTest, Post) { try { const std::string data = "{'name'='Adam', 'age'=20}"; - auto r = session.Request(webcc::RequestBuilder{}. - Post("http://httpbin.org/post"). - Body(data).Json() - ()); + auto r = session.Send(webcc::RequestBuilder{}. + Post("http://httpbin.org/post").Body(data).Json() + ()); EXPECT_EQ(webcc::Status::kOK, r->status()); EXPECT_EQ("OK", r->reason()); @@ -347,10 +341,9 @@ TEST(ClientTest, Post_FileBody) { } try { - auto r = session.Request(webcc::RequestBuilder{}. - Post("http://httpbin.org/post"). - File(path) // Use the file as body - ()); + auto r = session.Send(webcc::RequestBuilder{}. + Post("http://httpbin.org/post").File(path) + ()); EXPECT_EQ(webcc::Status::kOK, r->status()); EXPECT_EQ("OK", r->reason()); @@ -377,11 +370,10 @@ TEST(ClientTest, Post_Gzip_SmallData) { const std::string data = "{'name'='Adam', 'age'=20}"; // This doesn't really compress the body! - auto r = session.Request(webcc::RequestBuilder{}. - Post("http://httpbin.org/post"). - Body(data).Json(). - Gzip() - ()); + auto r = session.Send(webcc::RequestBuilder{}. + Post("http://httpbin.org/post").Body(data).Json(). + Gzip() + ()); //Json::Value json = StringToJson(r->data()); @@ -398,16 +390,15 @@ TEST(ClientTest, Post_Gzip) { try { // Use Boost.org home page as the POST data. - auto r1 = session.Request(webcc::RequestBuilder{}. - Get("https://www.boost.org/") - ()); + auto r1 = session.Send(webcc::RequestBuilder{}. + Get("https://www.boost.org/") + ()); const std::string& data = r1->data(); - auto r2 = session.Request(webcc::RequestBuilder{}. - Post("http://httpbin.org/post"). - Body(data).Gzip() - ()); + auto r2 = session.Send(webcc::RequestBuilder{}. + Post("http://httpbin.org/post").Body(data).Gzip() + ()); EXPECT_EQ(webcc::Status::kOK, r2->status()); EXPECT_EQ("OK", r2->reason()); @@ -440,33 +431,26 @@ TEST(ClientTest, KeepAlive) { try { // Keep-Alive by default. - auto r = session.Request(webcc::RequestBuilder{}.Get(url)()); + auto r = session.Send(webcc::RequestBuilder{}.Get(url)()); using boost::iequals; EXPECT_TRUE(iequals(r->GetHeader("Connection"), "Keep-alive")); // Close by setting Connection header directly. - r = session.Request(webcc::RequestBuilder{}. - Get(url). - Header("Connection", "Close") - ()); + r = session.Send(webcc::RequestBuilder{}.Get(url). + Header("Connection", "Close") + ()); EXPECT_TRUE(iequals(r->GetHeader("Connection"), "Close")); // Close by using request builder. - r = session.Request(webcc::RequestBuilder{}. - Get(url). - KeepAlive(false) - ()); + r = session.Send(webcc::RequestBuilder{}.Get(url).KeepAlive(false)()); EXPECT_TRUE(iequals(r->GetHeader("Connection"), "Close")); // Keep-Alive explicitly by using request builder. - r = session.Request(webcc::RequestBuilder{}. - Get(url). - KeepAlive(true) - ()); + r = session.Send(webcc::RequestBuilder{}.Get(url).KeepAlive(true)()); EXPECT_TRUE(iequals(r->GetHeader("Connection"), "Keep-alive")); diff --git a/examples/client_basics.cc b/examples/client_basics.cc index bb367e6..79a4f58 100644 --- a/examples/client_basics.cc +++ b/examples/client_basics.cc @@ -12,30 +12,28 @@ int main() { webcc::ResponsePtr r; try { - r = session.Request(webcc::RequestBuilder{}. - Get("http://httpbin.org/get"). - Query("name", "Adam Gu", /*encode*/true). - Header("Accept", "application/json"). - Date() - ()); + r = session.Send(webcc::RequestBuilder{}. + Get("http://httpbin.org/get"). + Query("name", "Adam Gu", /*encode*/true). + Header("Accept", "application/json").Date() + ()); assert(r->status() == webcc::Status::kOK); assert(!r->data().empty()); - r = session.Request(webcc::RequestBuilder{}. - Post("http://httpbin.org/post"). - Body("{'name'='Adam', 'age'=20}"). - Json().Utf8() - ()); + r = session.Send(webcc::RequestBuilder{}. + Post("http://httpbin.org/post"). + Body("{'name'='Adam', 'age'=20}").Json().Utf8() + ()); assert(r->status() == webcc::Status::kOK); assert(!r->data().empty()); #if WEBCC_ENABLE_SSL - r = session.Request(webcc::RequestBuilder{}. - Get("https://httpbin.org/get") - ()); + r = session.Send(webcc::RequestBuilder{}. + Get("https://httpbin.org/get") + ()); assert(r->status() == webcc::Status::kOK); assert(!r->data().empty()); diff --git a/examples/file_downloader.cc b/examples/file_downloader.cc index df9ad3d..5f3cb9f 100644 --- a/examples/file_downloader.cc +++ b/examples/file_downloader.cc @@ -26,8 +26,7 @@ int main(int argc, char* argv[]) { webcc::ClientSession session; try { - auto r = session.Request(webcc::RequestBuilder{}.Get(url)(), - true); // Stream the response data to file. + auto r = session.Send(webcc::RequestBuilder{}.Get(url)(), true); if (auto file_body = r->file_body()) { file_body->Move(path); diff --git a/examples/form_client.cc b/examples/form_client.cc index 2ed4313..e24db3f 100644 --- a/examples/form_client.cc +++ b/examples/form_client.cc @@ -41,11 +41,10 @@ int main(int argc, char* argv[]) { webcc::ClientSession session; try { - auto r = session.Request(webcc::RequestBuilder{}. - Post(url). - FormFile("file", upload_dir / "remember.txt"). - FormData("json", "{}", "application/json") - ()); + auto r = session.Send(webcc::RequestBuilder{}.Post(url). + FormFile("file", upload_dir / "remember.txt"). + FormData("json", "{}", "application/json") + ()); std::cout << r->status() << std::endl; diff --git a/examples/github_client.cc b/examples/github_client.cc index fa1d9eb..1d90848 100644 --- a/examples/github_client.cc +++ b/examples/github_client.cc @@ -55,9 +55,8 @@ void PrettyPrintJsonString(const std::string& str) { // List public events. void ListEvents(webcc::ClientSession& session) { try { - auto r = session.Request(webcc::RequestBuilder{}. - Get(kUrlRoot).Path("events") - ()); + auto r = session.Send(webcc::RequestBuilder{}.Get(kUrlRoot).Path("events") + ()); PRINT_JSON_STRING(r->data()); @@ -71,10 +70,9 @@ void ListEvents(webcc::ClientSession& session) { // ListUserFollowers(session, "") void ListUserFollowers(webcc::ClientSession& session, const std::string& user) { try { - auto r = session.Request(webcc::RequestBuilder{}. - Get(kUrlRoot).Path("users").Path(user). - Path("followers") - ()); + auto r = session.Send(webcc::RequestBuilder{}.Get(kUrlRoot). + Path("users").Path(user).Path("followers") + ()); PRINT_JSON_STRING(r->data()); @@ -90,10 +88,9 @@ void ListAuthUserFollowers(webcc::ClientSession& session, const std::string& login, const std::string& password) { try { - auto r = session.Request(webcc::RequestBuilder{}. - Get(kUrlRoot).Path("user/followers"). - AuthBasic(login, password) - ()); + auto r = session.Send(webcc::RequestBuilder{}.Get(kUrlRoot). + Path("user/followers").AuthBasic(login, password) + ()); PRINT_JSON_STRING(r->data()); @@ -112,12 +109,10 @@ void CreateAuthorization(webcc::ClientSession& session, " 'scopes': ['public_repo', 'repo', 'repo:status', 'user']\n" "}"; - auto r = session.Request(webcc::RequestBuilder{}. - Post(kUrlRoot).Path("authorizations"). - Body(std::move(data)). - Json().Utf8(). - AuthBasic(login, password) - ()); + auto r = session.Send(webcc::RequestBuilder{}.Post(kUrlRoot). + Path("authorizations").AuthBasic(login, password). + Body(std::move(data)).Json().Utf8() + ()); std::cout << r->data() << std::endl; diff --git a/examples/rest_book_client.cc b/examples/rest_book_client.cc index 75023cc..8102218 100644 --- a/examples/rest_book_client.cc +++ b/examples/rest_book_client.cc @@ -57,7 +57,7 @@ BookClient::BookClient(const std::string& url, int timeout) bool BookClient::ListBooks(std::list* books) { try { - auto r = session_.Request(WEBCC_GET(url_).Path("books")()); + auto r = session_.Send(WEBCC_GET(url_).Path("books")()); if (!CheckStatus(r, webcc::Status::kOK)) { // Response HTTP status error. @@ -89,9 +89,9 @@ bool BookClient::CreateBook(const std::string& title, double price, req_json["price"] = price; try { - auto r = session_.Request(WEBCC_POST(url_).Path("books"). - Body(JsonToString(req_json)) - ()); + auto r = session_.Send(WEBCC_POST(url_).Path("books"). + Body(JsonToString(req_json)) + ()); if (!CheckStatus(r, webcc::Status::kCreated)) { return false; @@ -110,7 +110,7 @@ bool BookClient::CreateBook(const std::string& title, double price, bool BookClient::GetBook(const std::string& id, Book* book) { try { - auto r = session_.Request(WEBCC_GET(url_).Path("books").Path(id)()); + auto r = session_.Send(WEBCC_GET(url_).Path("books").Path(id)()); if (!CheckStatus(r, webcc::Status::kOK)) { return false; @@ -131,9 +131,9 @@ bool BookClient::UpdateBook(const std::string& id, const std::string& title, json["price"] = price; try { - auto r = session_.Request(WEBCC_PUT(url_).Path("books").Path(id). - Body(JsonToString(json)) - ()); + auto r = session_.Send(WEBCC_PUT(url_).Path("books").Path(id). + Body(JsonToString(json)) + ()); if (!CheckStatus(r, webcc::Status::kOK)) { return false; @@ -149,7 +149,7 @@ bool BookClient::UpdateBook(const std::string& id, const std::string& title, bool BookClient::DeleteBook(const std::string& id) { try { - auto r = session_.Request(WEBCC_DELETE(url_).Path("books").Path(id)()); + auto r = session_.Send(WEBCC_DELETE(url_).Path("books").Path(id)()); if (!CheckStatus(r, webcc::Status::kOK)) { return false; diff --git a/webcc/client_session.cc b/webcc/client_session.cc index 3d8cdae..42cdf5d 100644 --- a/webcc/client_session.cc +++ b/webcc/client_session.cc @@ -28,7 +28,7 @@ void ClientSession::AuthToken(const std::string& token) { return Auth("Token", token); } -ResponsePtr ClientSession::Request(RequestPtr request, bool stream) { +ResponsePtr ClientSession::Send(RequestPtr request, bool stream) { assert(request); for (auto& h : headers_.data()) { @@ -44,7 +44,7 @@ ResponsePtr ClientSession::Request(RequestPtr request, bool stream) { request->Prepare(); - return Send(request, stream); + return DoSend(request, stream); } void ClientSession::InitHeaders() { @@ -85,7 +85,7 @@ void ClientSession::InitHeaders() { headers_.Set(kConnection, "Keep-Alive"); } -ResponsePtr ClientSession::Send(RequestPtr request, bool stream) { +ResponsePtr ClientSession::DoSend(RequestPtr request, bool stream) { const ClientPool::Key key{ request->url() }; // Reuse a pooled connection. diff --git a/webcc/client_session.h b/webcc/client_session.h index bbc3afe..c0dfea5 100644 --- a/webcc/client_session.h +++ b/webcc/client_session.h @@ -61,12 +61,12 @@ public: // the response body will be FileBody, and you can easily move the temp file // to another path with FileBody::Move(). So, |stream| is really useful for // downloading files (JPEG, etc.) or saving memory for huge data responses. - ResponsePtr Request(RequestPtr request, bool stream = false); + ResponsePtr Send(RequestPtr request, bool stream = false); private: void InitHeaders(); - ResponsePtr Send(RequestPtr request, bool stream); + ResponsePtr DoSend(RequestPtr request, bool stream); private: // Default media type for `Content-Type` header.