HTTP Client in C++: Making Requests Properly from A to Z
In the modern world of programming, interacting with remote servers via the HTTP protocol is one of the basic tasks. Whether it's getting data from an API, sending a form, or downloading a file — the ability to work with HTTP requests is essential for every C++ developer. In this article, we will look at how to create a full-fledged HTTP client in C++, review popular libraries, and best practices.
Why do you need an HTTP client in C++?
Unlike languages with built-in HTTP libraries (Python, JavaScript), C++ does not have a standard tool for working with HTTP in the standard library. However, this is not a problem, as there are several powerful and time-tested solutions:
- libcurl — the most popular and powerful library for working with URLs
- cpprestsdk (Casablanca) — a modern asynchronous library from Microsoft
- Boost.Beast — a library based on Boost.Asio for low-level work
In this article, we will focus on libcurl and cpprestsdk, as the most commonly used solutions.
Basics of working with libcurl
libcurl is a time-tested library that supports many protocols, including HTTP/1.1, HTTP/2, FTP, and others. It is written in C but has excellent bindings for C++.
Installing libcurl
Installing libcurl depends on your operating system:
# Ubuntu/Debiansudo apt-get install libcurl4-openssl-dev
# macOS (via Homebrew)brew install curl
# Windows (via vcpkg)vcpkg install curlSimple GET request with libcurl
Let's start with a basic example — sending a GET request and receiving a response:
#include <iostream>#include <curl/curl.h>#include <string>
// Callback function for writing datasize_t WriteCallback(void* contents, size_t size, size_t nmemb, std::string* output) { size_t totalSize = size * nmemb; output->append(static_cast<char*>(contents), totalSize); return totalSize;}
int main() { CURL* curl = curl_easy_init(); if (!curl) { std::cerr << "CURL initialization error" << std::endl; return 1; }
std::string response; curl_easy_setopt(curl, CURLOPT_URL, "https://jsonplaceholder.typicode.com/posts/1"); curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback); curl_easy_setopt(curl, CURLOPT_WRITEDATA, &response); CURLcode res = curl_easy_perform(curl); if (res != CURLE_OK) { std::cerr << "Request error: " << curl_easy_strerror(res) << std::endl; } else { std::cout << "Server response:" << std::endl; std::cout << response << std::endl; } curl_easy_cleanup(curl); return 0;}Sending a POST request with data
POST requests are used to send data to the server. Let's look at an example with JSON data:
#include <iostream>#include <curl/curl.h>#include <string>
size_t WriteCallback(void* contents, size_t size, size_t nmemb, std::string* output) { size_t totalSize = size * nmemb; output->append(static_cast<char*>(contents), totalSize); return totalSize;}
int main() { CURL* curl = curl_easy_init(); if (!curl) return 1;
std::string response; std::string jsonData = R"({"title": "foo", "body": "bar", "userId": 1})"; struct curl_slist* headers = nullptr; headers = curl_slist_append(headers, "Content-Type: application/json"); curl_easy_setopt(curl, CURLOPT_URL, "https://jsonplaceholder.typicode.com/posts"); curl_easy_setopt(curl, CURLOPT_POSTFIELDS, jsonData.c_str()); curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); curl_easy_