HTTP client in C++: making requests correctly from A to Z
\n\nIn the modern world of software development, the ability to interact with remote servers via HTTP is a fundamental skill. Whether it's downloading data from an API, submitting forms, or working with web services, C++ provides several powerful tools for creating HTTP clients. In this article, we will break down how to make HTTP requests correctly in C++, look at popular libraries, and write working code examples.
\n\nWhy C++ for HTTP requests?
\n\nC++ does not have built-in HTTP support in the standard library, unlike Python or JavaScript. However, this is not a problem: there are time-tested libraries that allow you to easily and efficiently send requests. The main options are:
\n\n- \n
- libcurl (cURL) — the most popular cross-platform library. \n
- Boost.Beast — a modern library based on Boost.Asio. \n
- WinHTTP — a built-in solution for Windows. \n
- Qt Network — for Qt projects. \n
In this article, we will focus on the first two, as they are the most versatile and suitable for most tasks.
\n\n1. HTTP client using libcurl
\n\nlibcurl is a time-tested library that supports HTTP, HTTPS, FTP, and many other protocols. It is easy to use and well-documented.
\n\nInstalling libcurl
\n\nFor Linux (Ubuntu/Debian):
\nsudo apt-get install libcurl4-openssl-dev\n\nFor Windows, you can download pre-built binaries from the official curl.se website or use vcpkg:
\nvcpkg install curl\n\nSimple GET request
\n\nLet's write a basic example of fetching data from a server:
\n\n#include <iostream>\n#include <string>\n#include <curl/curl.h>\n\n// Callback function for writing data\nstatic size_t WriteCallback(void* contents, size_t size, size_t nmemb, std::string* output) {\n size_t totalSize = size * nmemb;\n output->append((char*)contents, totalSize);\n return totalSize;\n}\n\nint main() {\n CURL* curl = curl_easy_init();\n if (!curl) {\n std::cerr << "CURL initialization error" << std::endl;\n return 1;\n }\n\n std::string response;\n curl_easy_setopt(curl, CURLOPT_URL, "https://jsonplaceholder.typicode.com/posts/1");\n curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback);\n curl_easy_setopt(curl, CURLOPT_WRITEDATA, &response);\n curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L); // Disable SSL verification for testing\n\n CURLcode res = curl_easy_perform(curl);\n if (res != CURLE_OK) {\n std::cerr << "Request error: " << curl_easy_strerror(res) << std::endl;\n } else {\n std::cout << "Server response:\\n" << response << std::endl;\n }\n\n curl_easy_cleanup(curl);\n return 0;\n}\n\nCompile with the -lcurl flag:
g++ -o http_client http_client.cpp -lcurl\n\nPOST request with JSON sending
\n\nNow let's add data sending:
\n\n#include <iostream>\n#include <string>\n#include <curl/curl.h>\n\nint main() {\n CURL* curl = curl_easy_init();\n if (!curl) return 1;\n\n std::string response;\n std::string jsonData = R"({"title": "foo", "body": "bar", "userId": 1})";\n\n struct curl_slist* headers = nullptr;\n headers = curl_slist_append(headers, "Content-Type: application/json");\n\n curl_easy_setopt(curl, CURLOPT_URL, "https://jsonplaceholder.typicode.com/posts");\n curl_easy_setopt(curl, CURLOPT_POSTFIELDS, jsonData.c_str());\n curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);\n curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCal