{"id":13418133,"url":"https://github.com/mrtazz/restclient-cpp","last_synced_at":"2025-05-14T07:08:31.527Z","repository":{"id":1124426,"uuid":"997856","full_name":"mrtazz/restclient-cpp","owner":"mrtazz","description":"C++ client for making HTTP/REST requests","archived":false,"fork":false,"pushed_at":"2025-01-03T11:02:58.000Z","size":4422,"stargazers_count":1590,"open_issues_count":35,"forks_count":381,"subscribers_count":87,"default_branch":"main","last_synced_at":"2025-04-12T23:29:39.116Z","etag":null,"topics":["c-plus-plus","http","http-client","libcurl","packagecloud","rest","rest-client","restclient"],"latest_commit_sha":null,"homepage":"http://code.mrtazz.com/restclient-cpp/","language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/mrtazz.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":".github/CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2010-10-18T15:13:05.000Z","updated_at":"2025-04-11T08:23:07.000Z","dependencies_parsed_at":"2024-05-02T00:53:15.387Z","dependency_job_id":"195f5e05-daa3-4716-b562-f8db880436dc","html_url":"https://github.com/mrtazz/restclient-cpp","commit_stats":{"total_commits":296,"total_committers":40,"mean_commits":7.4,"dds":"0.28378378378378377","last_synced_commit":"b782bd26539a3d1a8edcb6d8a3493b111f8fac66"},"previous_names":[],"tags_count":14,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mrtazz%2Frestclient-cpp","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mrtazz%2Frestclient-cpp/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mrtazz%2Frestclient-cpp/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mrtazz%2Frestclient-cpp/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mrtazz","download_url":"https://codeload.github.com/mrtazz/restclient-cpp/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254092775,"owners_count":22013290,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["c-plus-plus","http","http-client","libcurl","packagecloud","rest","rest-client","restclient"],"created_at":"2024-07-30T22:00:58.828Z","updated_at":"2025-05-14T07:08:31.509Z","avatar_url":"https://github.com/mrtazz.png","language":"C++","readme":"# REST client for C++\n![build status](https://github.com/mrtazz/restclient-cpp/actions/workflows/tests.yaml/badge.svg)\n[![Coverage Status](https://coveralls.io/repos/mrtazz/restclient-cpp/badge.svg?branch=master\u0026service=github)](https://coveralls.io/github/mrtazz/restclient-cpp?branch=master)\n[![Packagecloud](https://img.shields.io/badge/packagecloud-available-brightgreen.svg)](https://packagecloud.io/mrtazz/restclient-cpp)\n[![doxygen](https://img.shields.io/badge/doxygen-reference-blue.svg)](http://code.mrtazz.com/restclient-cpp/ref/)\n[![MIT license](https://img.shields.io/badge/license-MIT-blue.svg)](http://opensource.org/licenses/MIT)\n\n\n## About\nThis is a simple REST client for C++. It wraps [libcurl][] for HTTP requests.\n\n## Usage\nrestclient-cpp provides two ways of interacting with REST endpoints. There is\na simple one, which doesn't need you to configure an object to interact with\nan API. However the simple way doesn't provide a lot of configuration options\neither. So if you need more than just a simple HTTP call, you will probably\nwant to check out the advanced usage.\n\n### Simple Usage\nThe simple API is just some static methods modeled after the most common HTTP\nverbs:\n\n```cpp\n#include \"restclient-cpp/restclient.h\"\n\nRestClient::Response r = RestClient::get(\"http://url.com\")\nRestClient::Response r = RestClient::post(\"http://url.com/post\", \"application/json\", \"{\\\"foo\\\": \\\"bla\\\"}\")\nRestClient::Response r = RestClient::put(\"http://url.com/put\", \"application/json\", \"{\\\"foo\\\": \\\"bla\\\"}\")\nRestClient::Response r = RestClient::patch(\"http://url.com/patch\", \"application/json\", \"{\\\"foo\\\": \\\"bla\\\"}\")\nRestClient::Response r = RestClient::del(\"http://url.com/delete\")\nRestClient::Response r = RestClient::head(\"http://url.com\")\nRestClient::Response r = RestClient::options(\"http://url.com\")\n```\n\nThe response is of type [RestClient::Response][restclient_response] and has\nthree attributes:\n\n```cpp\nRestClient::Response.code // HTTP response code\nRestClient::Response.body // HTTP response body\nRestClient::Response.headers // HTTP response headers\n```\n\n### Advanced Usage\nHowever if you want more sophisticated features like connection reuse,\ntimeouts or authentication, there is also a different, more configurable way.\n\n```cpp\n#include \"restclient-cpp/connection.h\"\n#include \"restclient-cpp/restclient.h\"\n\n// initialize RestClient\nRestClient::init();\n\n// get a connection object\nRestClient::Connection* conn = new RestClient::Connection(\"http://url.com\");\n\n// configure basic auth\nconn-\u003eSetBasicAuth(\"WarMachine68\", \"WARMACHINEROX\");\n\n// set connection timeout to 5s\nconn-\u003eSetTimeout(5);\n\n// set custom user agent\n// (this will result in the UA \"foo/cool restclient-cpp/VERSION\")\nconn-\u003eSetUserAgent(\"foo/cool\");\n\n// enable following of redirects (default is off)\nconn-\u003eFollowRedirects(true);\n// and limit the number of redirects (default is -1, unlimited)\nconn-\u003eFollowRedirects(true, 3);\n\n// set headers\nRestClient::HeaderFields headers;\nheaders[\"Accept\"] = \"application/json\";\nconn-\u003eSetHeaders(headers)\n\n// append additional headers\nconn-\u003eAppendHeader(\"X-MY-HEADER\", \"foo\")\n\n// if using a non-standard Certificate Authority (CA) trust file\nconn-\u003eSetCAInfoFilePath(\"/etc/custom-ca.crt\")\n\nRestClient::Response r = conn-\u003eget(\"/get\")\nRestClient::Response r = conn-\u003ehead(\"/get\")\nRestClient::Response r = conn-\u003edel(\"/delete\")\nRestClient::Response r = conn-\u003eoptions(\"/options\")\n\n// set different content header for POST, PUT and PATCH\nconn-\u003eAppendHeader(\"Content-Type\", \"application/json\")\nRestClient::Response r = conn-\u003epost(\"/post\", \"{\\\"foo\\\": \\\"bla\\\"}\")\nRestClient::Response r = conn-\u003eput(\"/put\", \"application/json\", \"{\\\"foo\\\": \\\"bla\\\"}\")\nRestClient::Response r = conn-\u003epatch(\"/patch\", \"text/plain\", \"foobar\")\n\n// deinit RestClient. After calling this you have to call RestClient::init()\n// again before you can use it\nRestClient::disable();\n```\n\nThe responses are again of type [RestClient::Response][restclient_response]\nand have three attributes:\n\n```cpp\nRestClient::Response.code // HTTP response code\nRestClient::Response.body // HTTP response body\nRestClient::Response.headers // HTTP response headers\n```\n\nThe connection object also provides a simple way to get some diagnostics and\nmetrics information via `conn-\u003eGetInfo()`. The result is a\n`RestClient::Connection::Info` struct and looks like this:\n\n```cpp\ntypedef struct {\n  std::string base_url;\n  RestClients::HeaderFields headers;\n  int timeout;\n  struct {\n    std::string username;\n    std::string password;\n  } basicAuth;\n\n  std::string certPath;\n  std::string certType;\n  std::string keyPath;\n  std::string keyPassword;\n  std::string customUserAgent;\n  std::string uriProxy;\n  struct {\n    // total time of the last request in seconds Total time of previous\n    // transfer. See CURLINFO_TOTAL_TIME\n    int totalTime;\n    // time spent in DNS lookup in seconds Time from start until name\n    // resolving completed. See CURLINFO_NAMELOOKUP_TIME\n    int nameLookupTime;\n    // time it took until Time from start until remote host or proxy\n    // completed. See CURLINFO_CONNECT_TIME\n    int connectTime;\n    // Time from start until SSL/SSH handshake completed. See\n    // CURLINFO_APPCONNECT_TIME\n    int appConnectTime;\n    // Time from start until just before the transfer begins. See\n    // CURLINFO_PRETRANSFER_TIME\n    int preTransferTime;\n    // Time from start until just when the first byte is received. See\n    // CURLINFO_STARTTRANSFER_TIME\n    int startTransferTime;\n    // Time taken for all redirect steps before the final transfer. See\n    // CURLINFO_REDIRECT_TIME\n    int redirectTime;\n    // number of redirects followed. See CURLINFO_REDIRECT_COUNT\n    int redirectCount;\n  } lastRequest;\n} Info;\n```\n\n#### Persistent connections/Keep-Alive\nThe connection object stores the curl easy handle in an instance variable and\nuses that for the lifetime of the object. This means curl will [automatically\nreuse connections][curl_keepalive] made with that handle.\n\n### Progress callback\n\nTwo wrapper functions are provided to setup the progress callback for uploads/downloads.\n\nCalling `conn-\u003eSetFileProgressCallback(callback)` with a callback parameter matching the prototype `int progress_callback(void *clientp, double dltotal, double dlnow, double ultotal, double ulnow)` will setup the progress callback.\n\nCalling `conn-\u003eSetFileProgressCallbackData(data)` is optional. This will set the data pointer which is the first parameter fed back to the progress callback - `clientp`. If this isn't set then `clientp` will default to the connection object `conn`.\n\n```cpp\n// set CURLOPT_NOPROGRESS\n// set CURLOPT_PROGRESSFUNCTION\nconn-\u003eSetFileProgressCallback(progressFunc);\n// set CURLOPT_PROGRESSDATA\nconn-\u003eSetFileProgressCallbackData(data);\n```\n\n### Write callback\n\nA write callback function can be provided for processing data as it's received from a GET call (for instance the [Kubernetes Watch API](https://kubernetes.io/docs/reference/using-api/api-concepts/#efficient-detection-of-changes)).\n\nCalling `conn-\u003eSetWriteFunction(callback)` with a function parameter matching the prototype `size_t write_function(void *data, size_t size, size_t nmemb, void *userdata)int progress_callback(void *clientp, double dltotal, double dlnow, double ultotal, double ulnow)` will setup the write function.\n\nHere is an example of a write callback function, processing result data line by line.\n\n```cpp\nauto writeCallback = [](void *data, size_t size, size_t nmemb, void *userdata) -\u003e size_t\n{\n  size_t bytes = size * nmemb;\n  try\n  {\n      // Add to the buffer\n      auto res = reinterpret_cast\u003cRestClient::Response *\u003e(userdata);\n      res-\u003ebody.append(static_cast\u003cchar*\u003e(data), bytes);\n      // If the last character is not a new line, wait for the rest.\n      if ('\\n' != *(res-\u003ebody.end() - 1))\n      {\n          return bytes;\n      }\n      // Process data one line at a time.\n      std::stringstream stream(res-\u003ebody);\n      std::string line;\n      while (std::getline(stream, line))\n      {\n        // Do something with the line here...\n      }\n      // Done processing the line\n      res-\u003ebody.clear();\n  }\n  catch(std::exception e)\n  {\n      // Log caught exception here\n      return 0;\n  }\n  return bytes;\n};\n```\n\n## Error handling\nWhen restclient-cpp encounters an error, generally the error (or \"status\") code is returned in the `Response` (see\n[Response struct in restclient.h](https://github.com/mrtazz/restclient-cpp/blob/master/include/restclient-cpp/restclient.h)). This error code can be either\nan [HTTP error code](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status), or if a lower-level cURL error was encountered, it may be\na [CURLCode](https://curl.haxx.se/libcurl/c/libcurl-errors.html). Currently, libcurl only defines 92 error codes, which means\nthere is no overlap between cURL error codes and HTTP response codes (which start at 1xx). However, if in the future, libcurl defines more than 99\nerror codes, meaning that cURL errors overlap with the HTTP 1xx class of responses, restclient-cpp will return a -1 if the CURLCode is 100 or higher.\nIn this case, callers can use `GetInfo().lastRequest.curlCode` to inspect the actual cURL error.\n\n## Thread Safety\nrestclient-cpp leans heavily on libcurl as it aims to provide a thin wrapper\naround it. This means it adheres to the basic level of thread safety [provided\nby libcurl][curl_threadsafety]. The `RestClient::init()` and\n`RestClient::disable()` methods basically correspond to `curl_global_init` and\n`curl_global_cleanup` and thus need to be called right at the beginning of\nyour program and before shutdown respectively. These set up the environment\nand are **not thread-safe**. After that you can create connection objects in\nyour threads. Do not share connection objects across threads as this would\nmean accessing curl handles from multiple threads at the same time which is\nnot allowed.\n\nThe connection level method SetNoSignal can be set to skip all signal handling. This is important in multi-threaded applications as DNS resolution timeouts use signals. The signal handlers quite readily get executed on other threads. Note that with this option DNS resolution timeouts do not work. If you have crashes in your multi-threaded executable that appear to be in DNS resolution, this is probably why.\n\nIn order to provide an easy to use API, the simple usage via the static\nmethods implicitly calls the curl global functions and is therefore also **not\nthread-safe**.\n\n## HTTPS User Certificate\n\nSimple wrapper functions are provided to allow clients to authenticate using certificates.\nUnder the hood these wrappers set cURL options, e.g. `CURLOPT_SSLCERT`, using `curl_easy_setopt`.\nNote: currently `libcurl` compiled with `gnutls` (e.g. `libcurl4-gnutls-dev` on\nubuntu) is buggy in that it returns a wrong error code when these options are set to invalid values.\n\n```cpp\n// set CURLOPT_SSLCERT\nconn-\u003eSetCertPath(certPath);\n// set CURLOPT_SSLCERTTYPE\nconn-\u003eSetCertType(type);\n// set CURLOPT_SSLKEY\nconn-\u003eSetKeyPath(keyPath);\n// set CURLOPT_KEYPASSWD\nconn-\u003eSetKeyPassword(keyPassword);\n```\n\n## HTTP Proxy Tunneling Support\n\nAn HTTP Proxy can be set to use for the upcoming request.\nTo specify a port number, append :[port] to the end of the host name. If not specified, `libcurl` will default to using port 1080 for proxies. The proxy string may be prefixed with `http://` or `https://`. If no HTTP(S) scheme is specified, the address provided to `libcurl` will be prefixed with `http://` to specify an HTTP proxy. A proxy host string can embedded user + password.\nThe operation will be tunneled through the proxy as curl option `CURLOPT_HTTPPROXYTUNNEL` is enabled by default.\nA numerical IPv6 address must be written within [brackets].\n\n```cpp\n// set CURLOPT_PROXY\nconn-\u003eSetProxy(\"https://37.187.100.23:3128\");\n/* or you can set it without the protocol scheme and\nhttp:// will be prefixed by default */\nconn-\u003eSetProxy(\"37.187.100.23:3128\");\n/* the following request will be tunneled through the proxy */\nRestClient::Response res = conn-\u003eget(\"/get\");\n```\n\n## Unix Socket Support\n\n- https://docs.docker.com/develop/sdk/examples/\n- $ curl --unix-socket /var/run/docker.sock http:/v1.24/containers/json\n\nNote that the URL used with a unix socket has only ONE leading forward slash.\n\n```cpp\nRestClient::Connection* conn = new RestClient::Connection(\"http:/v1.30\");\nconn-\u003eSetUnixSocketPath(\"/var/run/docker.sock\");\nRestClient::HeaderFields headers;\nheaders[\"Accept\"] = \"application/json; charset=UTF-8\";\nheaders[\"Expect\"] = \"\";\nconn-\u003eSetHeaders(headers);\nauto resp = conn-\u003eget(\"/images/json\");\n```\n\n## Dependencies\n- [libcurl][]\n\n## Installation\nThere are some packages available for Linux on [packagecloud][packagecloud].\nAnd for OSX you can get it from the mrtazz/oss homebrew tap:\n\n```bash\nbrew tap mrtazz/oss\nbrew install restclient-cpp\n```\n\nOtherwise you can do the regular autotools dance:\n\n```bash\n./autogen.sh\n./configure\nmake install\n```\n\nAlternatively, you can build and install restclient-cpp using [vcpkg](https://github.com/microsoft/vcpkg/) dependency manager:\n\n```bash\ngit clone https://github.com/Microsoft/vcpkg.git\ncd vcpkg\n./bootstrap-vcpkg.sh\n./vcpkg integrate install\n./vcpkg install restclient-cpp\n```\n\nThe restclient-cpp port in vcpkg is kept up to date by Microsoft team members and community contributors.\nIf the version is out of date, please [create an issue or pull request](https://github.com/Microsoft/vcpkg) on the vcpkg repository.\n\nAnother option is to use Mingw64 and CMake to compile on Windows. This requires you to have [Mingw64](https://www.mingw-w64.org/) installed with [CMake](https://cmake.org/download/) and [libCurl](https://curl.se/windows/) (MSYS2 would also work fine).\n\n```bash\n# Make sure cmake, mingw32-make and g++ are in PATH\n# Clone the repo\ngit clone https://github.com/mrtazz/restclient-cpp \u0026\u0026 cd restclient-cpp\n# Build library\nmkdir build \u0026\u0026 cd build\n# Run cmake\ncmake -DCMAKE_CXX_COMPILER=g++ -DCMAKE_CC_COMPILER=gcc -DCMAKE_MAKE_PROGRAM=mingw32-make -G \"MinGW Makefiles\" ..\n# Builds the dll.a lib and dll file\nmingw32-make\n```\n\n## Contribute\nAll contributions are highly appreciated. This includes filing issues,\nupdating documentation and writing code. Please take a look at the\n[contributing guidelines][contributing] before so your contribution can be\nmerged as fast as possible.\n\n\n[libcurl]: http://curl.haxx.se/libcurl/\n[gtest]: http://code.google.com/p/googletest/\n[packagecloud]: https://packagecloud.io/mrtazz/restclient-cpp\n[contributing]: https://github.com/mrtazz/restclient-cpp/blob/master/.github/CONTRIBUTING.md\n[curl_keepalive]: http://curl.haxx.se/docs/faq.html#What_about_Keep_Alive_or_persist\n[curl_threadsafety]: http://curl.haxx.se/libcurl/c/threadsafe.html\n[restclient_response]: http://code.mrtazz.com/restclient-cpp/ref/struct_rest_client_1_1_response.html\n","funding_links":[],"categories":["TODO scan for Android support in followings","Networking","Communication Clients","内存分配"],"sub_categories":["fake data","网络"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmrtazz%2Frestclient-cpp","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmrtazz%2Frestclient-cpp","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmrtazz%2Frestclient-cpp/lists"}