├── win-vsproj
├── example
│ ├── .gitignore
│ ├── example.vcxproj.user
│ ├── .editorconfig
│ ├── example.vcxproj.filters
│ └── example.vcxproj
├── iclient
│ ├── iclient.vcxproj.user
│ ├── .editorconfig
│ ├── iclient.vcxproj.filters
│ └── iclient.vcxproj
└── iclient.sln
├── .gitignore
├── assets
└── README
│ ├── download_range.jpg
│ ├── release-v1.0.1.jpg
│ └── breakpoint_continue.jpg
├── include
├── iclient
│ ├── iclient.h
│ ├── curl_inc.h
│ ├── url.h
│ ├── response.h
│ ├── http.h
│ └── request.h
└── curl
│ ├── stdcheaders.h
│ ├── mprintf.h
│ ├── options.h
│ ├── header.h
│ ├── curlver.h
│ ├── easy.h
│ ├── urlapi.h
│ ├── multi.h
│ └── system.h
├── .vscode
├── c_cpp_properties.json
└── launch.json
├── xmake.lua
├── src
├── util.h
├── executor.h
├── url.cpp
├── util.cpp
├── response.cpp
├── request.cpp
├── executor.cpp
└── http.cpp
├── example
├── test_http_post.cpp
├── test_http_put.cpp
├── test_url.cpp
├── test_http_get.cpp
├── test_download.cpp
├── test_download_speed_limit.cpp
├── test_download_resume.cpp
├── test_download_range.cpp
└── main.cpp
├── LICENSE
├── README.md
└── makefile
/win-vsproj/example/.gitignore:
--------------------------------------------------------------------------------
1 | test_download*
2 | dl_part*
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | bin
2 | build
3 | lib
4 | .xmake
5 | *.jpg
6 | *.dat
7 | win-vsproj/build
8 | win-vsproj/.vs
9 |
--------------------------------------------------------------------------------
/assets/README/download_range.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Leopard-C/iclient/HEAD/assets/README/download_range.jpg
--------------------------------------------------------------------------------
/assets/README/release-v1.0.1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Leopard-C/iclient/HEAD/assets/README/release-v1.0.1.jpg
--------------------------------------------------------------------------------
/assets/README/breakpoint_continue.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Leopard-C/iclient/HEAD/assets/README/breakpoint_continue.jpg
--------------------------------------------------------------------------------
/include/iclient/iclient.h:
--------------------------------------------------------------------------------
1 | #ifndef IC_CLIENT_H_
2 | #define IC_CLIENT_H_
3 |
4 | #include "request.h"
5 | #include "response.h"
6 | #include "url.h"
7 |
8 | #endif // IC_CLIENT_H_
9 |
--------------------------------------------------------------------------------
/win-vsproj/example/example.vcxproj.user:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/win-vsproj/iclient/iclient.vcxproj.user:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/win-vsproj/example/.editorconfig:
--------------------------------------------------------------------------------
1 | root = true
2 |
3 | [*.{h,c,cpp,hpp,inc,inl,js,json}]
4 | charset = utf-8
5 | indent_style = space
6 | indent_size = 4
7 | insert_final_newline = true
8 | trim_trailing_whitespace = true
9 |
10 | [*.{html,js,css,svg}]
11 | charset = utf-8
12 | indent_style = space
13 | indent_size = 2
14 |
15 |
--------------------------------------------------------------------------------
/win-vsproj/iclient/.editorconfig:
--------------------------------------------------------------------------------
1 | root = true
2 |
3 | [*.{h,c,cpp,hpp,inc,inl,js,json}]
4 | charset = utf-8
5 | indent_style = space
6 | indent_size = 4
7 | insert_final_newline = true
8 | trim_trailing_whitespace = true
9 |
10 | [*.{html,js,css,svg}]
11 | charset = utf-8
12 | indent_style = space
13 | indent_size = 2
14 |
15 |
--------------------------------------------------------------------------------
/.vscode/c_cpp_properties.json:
--------------------------------------------------------------------------------
1 | {
2 | "configurations": [
3 | {
4 | "name": "Linux",
5 | "includePath": [
6 | "${workspaceFolder}/include",
7 | "${default}"
8 | ],
9 | "defines": [],
10 | "cStandard": "c11",
11 | "cppStandard": "gnu++11",
12 | "intelliSenseMode": "linux-gcc-x64"
13 | }
14 | ],
15 | "version": 4
16 | }
--------------------------------------------------------------------------------
/include/iclient/curl_inc.h:
--------------------------------------------------------------------------------
1 | /**
2 | * @file curl_inc.h
3 | * @brief include libcurl header file here.
4 | * @author Leopard-C (leopard.c@outlook.com)
5 | * @version 0.1
6 | * @date 2023-01-12
7 | *
8 | * @copyright Copyright (c) 2021-present, Jinbao Chen.
9 | */
10 | #ifndef IC_CLIENT_CURL_INC_H_
11 | #define IC_CLIENT_CURL_INC_H_
12 |
13 | #ifndef BUILDING_LIBCURL
14 | # define BUILDING_LIBCURL
15 | #endif
16 |
17 | #include
18 |
19 | #endif // IC_CLIENT_CURL_INC_H_
20 |
--------------------------------------------------------------------------------
/xmake.lua:
--------------------------------------------------------------------------------
1 |
2 | add_rules("mode.debug", "mode.release")
3 | set_policy("build.warning", true)
4 | set_languages("c99", "cxx11")
5 | add_cxflags("-Wreturn-type", "-Wsign-compare", "-Wunused", "-Wswitch")
6 | add_cxflags("-Wno-deprecated-declarations")
7 |
8 | add_includedirs("include")
9 |
10 | target("iclient")
11 | set_kind("static")
12 | add_files("src/*.cpp")
13 | add_links("curl", "pthread", "dl")
14 | set_targetdir("lib/linux/$(arch)")
15 |
16 | target("example.out")
17 | set_kind("binary")
18 | add_files("example/*.cpp")
19 | add_deps("iclient")
20 | set_targetdir("bin")
21 |
--------------------------------------------------------------------------------
/.vscode/launch.json:
--------------------------------------------------------------------------------
1 | {
2 | "version": "0.2.0",
3 | "configurations": [
4 | {
5 | "name": "g++-10 - Build and debug active file",
6 | "type": "cppdbg",
7 | "request": "launch",
8 | "program": "${workspaceFolder}/bin/example.out",
9 | "stopAtEntry": false,
10 | "cwd": "${workspaceFolder}",
11 | "environment": [],
12 | "externalConsole": false,
13 | "MIMode": "gdb",
14 | "setupCommands": [
15 | {
16 | "description": "Enable pretty-printing for gdb",
17 | "text": "-enable-pretty-printing",
18 | "ignoreFailures": true
19 | }
20 | ],
21 | "miDebuggerPath": "/usr/bin/gdb",
22 | "sourceFileMap": {}
23 | }
24 | ],
25 | "logging": {
26 | "engineLogging": true,
27 | "traceResponse": true
28 | }
29 | }
--------------------------------------------------------------------------------
/src/util.h:
--------------------------------------------------------------------------------
1 | #ifndef IC_CLIENT_UTIL_H_
2 | #define IC_CLIENT_UTIL_H_
3 |
4 | #include
5 | #include
6 |
7 | namespace ic {
8 | namespace client {
9 | namespace util {
10 |
11 | /**
12 | * @brief URL encode
13 | */
14 | std::string escape(const std::string& str);
15 |
16 | /**
17 | * @brief URL decode
18 | */
19 | std::string unescape(const std::string& str);
20 |
21 | /**
22 | * @brief Merge string array
23 | * @param strs string array
24 | * @param sep separator string
25 | */
26 | std::string join(const std::vector& strs, const std::string& sep);
27 |
28 | std::string& trim(std::string& str);
29 |
30 | std::string& to_upper(std::string& str);
31 | std::string& to_lower(std::string& str);
32 |
33 | long get_file_size(const std::string& filename);
34 |
35 | /**
36 | * @brief Calculate "Host" filed in request header
37 | */
38 | std::string get_host(const std::string& url);
39 |
40 | } // namespace util
41 | } // namespace client
42 | } // namespace ic
43 |
44 | #endif // IC_CLIENT_UTIL_H_
45 |
--------------------------------------------------------------------------------
/example/test_http_post.cpp:
--------------------------------------------------------------------------------
1 | #include "iclient/iclient.h"
2 |
3 | void test_http_post() {
4 | using namespace ic::client;
5 | Request request("http://httpbin.org/post");
6 | request.set_http_method(http::Method::HTTP_POST);
7 | request.set_header("accept", "application/json");
8 |
9 | auto response = request.Perform();
10 |
11 | printf("----------------------------------------------\n");
12 | printf("%s\n", to_string(response.status()));
13 | printf("----------------------------------------------\n");
14 | if (response.ok()) {
15 | // Header
16 | printf("------ Headers -------------------------------\n");
17 | for (auto& header : response.headers()) {
18 | printf("%s: %s\n", header.first.c_str(), header.second.c_str());
19 | }
20 | // Data
21 | printf("------ Body ----------------------------------\n");
22 | printf("%s\n", response.data().c_str());
23 | printf("---------------------------------------------\n");
24 | }
25 | printf("\n\n");
26 | }
27 |
--------------------------------------------------------------------------------
/example/test_http_put.cpp:
--------------------------------------------------------------------------------
1 | #include "iclient/iclient.h"
2 |
3 | void test_http_put() {
4 | using namespace ic::client;
5 | Request request("http://httpbin.org/put");
6 | request.set_http_method(http::Method::HTTP_PUT);
7 | request.set_header("accept", "application/json");
8 | auto response = request.Perform();
9 |
10 | printf("----------------------------------------------\n");
11 | printf("%s\n", ic::client::to_string(response.status()));
12 | printf("----------------------------------------------\n");
13 | if (response.ok()) {
14 | // Header
15 | printf("------ Headers -------------------------------\n");
16 | for (auto& header : response.headers()) {
17 | printf("%s: %s\n", header.first.c_str(), header.second.c_str());
18 | }
19 | // Data
20 | printf("------ Body ----------------------------------\n");
21 | printf("%s\n", response.data().c_str());
22 | printf("---------------------------------------------\n");
23 | }
24 | printf("\n\n");
25 | }
26 |
--------------------------------------------------------------------------------
/example/test_url.cpp:
--------------------------------------------------------------------------------
1 | #include "iclient/iclient.h"
2 |
3 | void test_url() {
4 | using namespace ic::client;
5 | Url url("https://api.icrystal.top/util/random");
6 | url.SetParam("min", "1");
7 | url.SetParam("max", "100");
8 | url.SetParam("count", "20");
9 | printf("GET: %s\n", url.ToString().c_str());
10 |
11 | Request request(url.ToString());
12 | request.set_verify_ssl(false);
13 | auto response = request.Perform();
14 |
15 | if (response.ok()) {
16 | // Header
17 | printf("------ Headers -------------------------------\n");
18 | for (auto& header : response.headers()) {
19 | printf("%s: %s\n", header.first.c_str(), header.second.c_str());
20 | }
21 | // Data
22 | printf("------ Body ----------------------------------\n");
23 | printf("%s\n", response.data().c_str());
24 | printf("---------------------------------------------\n");
25 | }
26 | else {
27 | printf("Request Error: %s %s\n", to_string(response.status()), http::to_string(response.http_status_code()));
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2021 Leopard-C
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/example/test_http_get.cpp:
--------------------------------------------------------------------------------
1 | #include "iclient/iclient.h"
2 |
3 | void test_http_get() {
4 | ic::client::Request request("http://httpbin.org/ip");
5 | ic::client::Response response = request.Perform();
6 |
7 | printf("---------------------------------------------\n");
8 | printf("%s\n", ic::client::to_string(response.status()));
9 | printf("---------------------------------------------\n");
10 | if (response.status() == ic::client::Status::SUCCESS
11 | && response.http_status_code() == ic::client::http::StatusCode::HTTP_200_OK) // equal to response.ok()
12 | {
13 | // Header
14 | printf("------ Headers -------------------------------\n");
15 | auto& headers = response.headers();
16 | for (auto& header : headers) {
17 | printf("%s: %s\n", header.first.c_str(), header.second.c_str());
18 | }
19 | // Data
20 | printf("------ Body ----------------------------------\n");
21 | printf("%s\n", response.data().c_str());
22 | printf("---------------------------------------------\n");
23 | }
24 | printf("\n\n");
25 | }
26 |
--------------------------------------------------------------------------------
/src/executor.h:
--------------------------------------------------------------------------------
1 | #ifndef IC_CLIENT_EXECUTOR_H_
2 | #define IC_CLIENT_EXECUTOR_H_
3 |
4 | #include "iclient/request.h"
5 | #include "iclient/response.h"
6 | #include "iclient/curl_inc.h"
7 |
8 | namespace ic {
9 | namespace client {
10 |
11 | class Executor {
12 | friend class Request;
13 | friend class Response;
14 | public:
15 | Executor(Request& request, Response& response);
16 | ~Executor();
17 |
18 | void Perform();
19 |
20 | void Reset();
21 |
22 | public:
23 | friend size_t curl_write_header(char* buffer, size_t size, size_t nitems, void* user_ptr);
24 | friend size_t curl_write_data(void* buffer, size_t size, size_t nitems, void* user_ptr);
25 | friend int curl_xfer_info(void* clientp, curl_off_t download_total_bytes, curl_off_t download_now_bytes,
26 | curl_off_t upload_total_bytes, curl_off_t upload_now_bytes);
27 |
28 | private:
29 | bool Prepare();
30 |
31 | private:
32 | CURL* curl_{nullptr};
33 | FILE* file_stream_{nullptr};
34 | curl_mime* curl_mime_{nullptr};
35 | curl_slist* curl_request_headers_{nullptr};
36 | Request& request_;
37 | Response& response_;
38 | };
39 |
40 | } // namespace client
41 | } // namespace ic
42 |
43 | #endif // IC_CLIENT_EXECUTOR_H_
44 |
--------------------------------------------------------------------------------
/example/test_download.cpp:
--------------------------------------------------------------------------------
1 | #include "iclient/iclient.h"
2 |
3 | /* download file url */
4 | extern const char* g_test_download_file_url;
5 |
6 | /* Progress bar */
7 | bool g_curl_xfer_info(const ic::client::Request& request,
8 | curl_off_t download_total_bytes, curl_off_t download_now_bytes,
9 | curl_off_t upload_total_bytes, curl_off_t upload_now_bytes);
10 | void reset_progress_bar();
11 |
12 | void test_download() {
13 | reset_progress_bar();
14 | ic::client::Request request(g_test_download_file_url);
15 | request.set_verify_ssl(false);
16 | request.set_download_file("test_download.jpg");
17 | request.set_transfer_progress_handler(g_curl_xfer_info);
18 |
19 | auto response = request.Perform();
20 |
21 | printf("iclient status: %s\n", ic::client::to_string(response.status()));
22 | if (response.status() == ic::client::Status::SUCCESS
23 | && response.http_status_code() == ic::client::http::StatusCode::HTTP_200_OK) // equal to response.ok()
24 | {
25 | printf("------ Headers ------------------------------\n");
26 | auto& headers = response.headers();
27 | for (auto& header : headers) {
28 | printf("%s: %s\n", header.first.c_str(), header.second.c_str());
29 | }
30 | }
31 | printf("\n\n");
32 | }
33 |
34 |
--------------------------------------------------------------------------------
/include/curl/stdcheaders.h:
--------------------------------------------------------------------------------
1 | #ifndef CURLINC_STDCHEADERS_H
2 | #define CURLINC_STDCHEADERS_H
3 | /***************************************************************************
4 | * _ _ ____ _
5 | * Project ___| | | | _ \| |
6 | * / __| | | | |_) | |
7 | * | (__| |_| | _ <| |___
8 | * \___|\___/|_| \_\_____|
9 | *
10 | * Copyright (C) 1998 - 2022, Daniel Stenberg, , et al.
11 | *
12 | * This software is licensed as described in the file COPYING, which
13 | * you should have received as part of this distribution. The terms
14 | * are also available at https://curl.se/docs/copyright.html.
15 | *
16 | * You may opt to use, copy, modify, merge, publish, distribute and/or sell
17 | * copies of the Software, and permit persons to whom the Software is
18 | * furnished to do so, under the terms of the COPYING file.
19 | *
20 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
21 | * KIND, either express or implied.
22 | *
23 | * SPDX-License-Identifier: curl
24 | *
25 | ***************************************************************************/
26 |
27 | #include
28 |
29 | size_t fread(void *, size_t, size_t, FILE *);
30 | size_t fwrite(const void *, size_t, size_t, FILE *);
31 |
32 | int strcasecmp(const char *, const char *);
33 | int strncasecmp(const char *, const char *, size_t);
34 |
35 | #endif /* CURLINC_STDCHEADERS_H */
36 |
--------------------------------------------------------------------------------
/example/test_download_speed_limit.cpp:
--------------------------------------------------------------------------------
1 | #include "iclient/iclient.h"
2 |
3 | /* download file url */
4 | extern const char* g_test_download_file_url;
5 |
6 | /* Progress bar */
7 | bool g_curl_xfer_info(const ic::client::Request& request,
8 | curl_off_t download_total_bytes, curl_off_t download_now_bytes,
9 | curl_off_t upload_total_bytes, curl_off_t upload_now_bytes);
10 | void reset_progress_bar();
11 |
12 | static void test_download_speed_limit_KBps(int speed) {
13 | reset_progress_bar();
14 | ic::client::Request request(g_test_download_file_url);
15 | request.set_verify_ssl(false);
16 | char filename[128];
17 | sprintf(filename, "test_download_speed_limit_%d.jpg", speed);
18 | request.set_download_file(filename);
19 | request.set_transfer_progress_handler(g_curl_xfer_info);
20 | request.set_max_download_speed(speed * 1024);
21 | printf("Speed Limit: %dKB/s\n", speed);
22 |
23 | auto response = request.Perform();
24 |
25 | printf("iclient status: %s\n", ic::client::to_string(response.status()));
26 | if (response.status() == ic::client::Status::SUCCESS
27 | && response.http_status_code() == ic::client::http::StatusCode::HTTP_200_OK)
28 | {
29 | printf("------ Headers ------------------------------\n");
30 | auto& headers = response.headers();
31 | for (auto& header : headers) {
32 | printf("%s: %s\n", header.first.c_str(), header.second.c_str());
33 | }
34 | }
35 | printf("\n\n");
36 | }
37 |
38 | void test_download_speed_limit() {
39 | test_download_speed_limit_KBps(256);
40 | test_download_speed_limit_KBps(512);
41 | test_download_speed_limit_KBps(1024);
42 | }
43 |
--------------------------------------------------------------------------------
/win-vsproj/example/example.vcxproj.filters:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01}
6 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms
7 |
8 |
9 | {f76de158-701c-444d-898e-62b134418908}
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 | source
18 |
19 |
20 | source
21 |
22 |
23 | source
24 |
25 |
26 | source
27 |
28 |
29 | source
30 |
31 |
32 | source
33 |
34 |
35 | source
36 |
37 |
38 | source
39 |
40 |
41 | source
42 |
43 |
44 |
--------------------------------------------------------------------------------
/src/url.cpp:
--------------------------------------------------------------------------------
1 | #include "iclient/url.h"
2 | #include "util.h"
3 |
4 | namespace ic {
5 | namespace client {
6 |
7 | void Url::set_base_url(const std::string& base_url) {
8 | baseurl_changed_ = true;
9 | base_url_ = base_url;
10 | util::trim(base_url_);
11 | auto pos = base_url_.find('?');
12 | if (pos != std::string::npos) {
13 | base_url_ = base_url_.substr(0, pos);
14 | }
15 | }
16 |
17 | void Url::AddParam(const std::string& key, const std::string& value) {
18 | params_.emplace(key, value);
19 | params_changed_ = true;
20 | }
21 |
22 | void Url::SetParam(const std::string& key, const std::string& value) {
23 | RemoveParam(key);
24 | AddParam(key, value);
25 | }
26 |
27 | void Url::RemoveParam(const std::string& key) {
28 | auto pair = params_.equal_range(key);
29 | if (pair.first != pair.second) {
30 | params_.erase(pair.first, pair.second);
31 | params_changed_ = true;
32 | }
33 | }
34 |
35 | void Url::ClearParams() {
36 | std::multimap().swap(params_);
37 | params_changed_ = true;
38 | }
39 |
40 | const std::string& Url::ToString() {
41 | if (!baseurl_changed_ && !params_changed_) {
42 | return url_;
43 | }
44 | url_ = base_url_;
45 | if (!params_.empty()) {
46 | url_ += '?' + GetParamsString();
47 | }
48 | baseurl_changed_ = false;
49 | params_changed_ = false;
50 | return url_;
51 | }
52 |
53 | const std::string& Url::GetParamsString() {
54 | if (!params_changed_) {
55 | return params_str_;
56 | }
57 | params_changed_ = false;
58 | params_str_.clear();
59 | if (params_.empty()) {
60 | return params_str_;
61 | }
62 | for (const auto& p : params_) {
63 | params_str_ += p.first;
64 | params_str_ += '=';
65 | params_str_ += util::escape(p.second);
66 | params_str_ += '&';
67 | }
68 | params_str_.pop_back();
69 | return params_str_;
70 | }
71 |
72 | } // namespace client
73 | } // namespace ic
74 |
--------------------------------------------------------------------------------
/example/test_download_resume.cpp:
--------------------------------------------------------------------------------
1 | #include "iclient/iclient.h"
2 |
3 | /* download file url */
4 | extern const char* g_test_download_file_url;
5 |
6 | /* Progress bar */
7 | bool g_curl_xfer_info(const ic::client::Request& request,
8 | curl_off_t download_total_bytes, curl_off_t download_now_bytes,
9 | curl_off_t upload_total_bytes, curl_off_t upload_now_bytes);
10 | void reset_progress_bar();
11 |
12 | // defined in test_download_range.cpp
13 | void download_range(const std::string& url, const std::string& local_file, size_t bytes_start, size_t bytes_end);
14 |
15 | // defined in the end of this file
16 | void download_resume(const std::string& url, const std::string& local_file);
17 |
18 |
19 | void test_download_resume() {
20 | /* Download first 4096 bytes */
21 | download_range(g_test_download_file_url, "test_download_resume.jpg", 0, 4095);
22 |
23 | /* resume: breakpoint continuation */
24 | /* download data remain */
25 | download_resume(g_test_download_file_url, "test_download_resume.jpg");
26 | }
27 |
28 | /**
29 | * @brief Get local file size
30 | */
31 | static long get_file_size(const std::string& filename) {
32 | FILE* fp = fopen(filename.c_str(), "rb");
33 | if (!fp) {
34 | return -1;
35 | }
36 | fseek(fp, 0L, SEEK_END);
37 | long size = ftell(fp);
38 | //fseek(fp, 0L, SEEK_SET);
39 | fclose(fp);
40 | return size;
41 | }
42 |
43 | void download_resume(const std::string& url, const std::string& local_file) {
44 | reset_progress_bar();
45 | printf("downloading %s\n", url.c_str());
46 | printf("local file: %s\n", local_file.c_str());
47 | printf("resume from: %ld bytes\n", get_file_size(local_file));
48 |
49 | ic::client::Request request(url);
50 | request.set_verify_ssl(false);
51 | request.set_download_file(local_file, true);
52 | request.set_transfer_progress_handler(g_curl_xfer_info);
53 |
54 | auto response = request.Perform();
55 |
56 | printf("iclient status: %s\n", ic::client::to_string(response.status()));
57 | printf("\n\n");
58 | }
59 |
--------------------------------------------------------------------------------
/include/iclient/url.h:
--------------------------------------------------------------------------------
1 | /**
2 | * @file url.h
3 | * @author Leopard-C (leopard.c@outlook.com)
4 | * @version 0.1
5 | * @date 2023-01-12
6 | *
7 | * @copyright Copyright (c) 2021-present, Jinbao Chen.
8 | */
9 | #ifndef IC_CLIENT_URL_H_
10 | #define IC_CLIENT_URL_H_
11 | #include