HTTP-Client in C++: Anfragen richtig stellen von A bis Z
In der modernen Programmierwelt ist die Interaktion mit entfernten Servern über das HTTP-Protokoll eine grundlegende Aufgabe. Ob es um das Abrufen von Daten von einer API, das Senden eines Formulars oder das Hochladen einer Datei geht – die Fähigkeit, mit HTTP-Anfragen zu arbeiten, ist für jeden C++-Entwickler notwendig. In diesem Artikel werden wir untersuchen, wie man einen vollwertigen HTTP-Client in C++ erstellt, gängige Bibliotheken und bewährte Verfahren betrachten.
Warum braucht man einen HTTP-Client in C++?
Im Gegensatz zu Sprachen mit integrierten HTTP-Bibliotheken (Python, JavaScript) verfügt C++ in der Standardbibliothek über kein Standardwerkzeug für die Arbeit mit HTTP. Dies ist jedoch kein Problem, da es mehrere leistungsstarke und bewährte Lösungen gibt:
- libcurl – die beliebteste und leistungsstärkste Bibliothek für die Arbeit mit URLs
- cpprestsdk (Casablanca) – eine moderne asynchrone Bibliothek von Microsoft
- Boost.Beast – eine Bibliothek basierend auf Boost.Asio für die Arbeit auf niedriger Ebene
In diesem Artikel konzentrieren wir uns auf libcurl und cpprestsdk, da sie die am häufigsten verwendeten Lösungen sind.
Grundlagen der Arbeit mit libcurl
libcurl ist eine bewährte Bibliothek, die viele Protokolle unterstützt, darunter HTTP/1.1, HTTP/2, FTP und andere. Sie ist in C geschrieben, hat aber hervorragende Bindings für C++.
Installation von libcurl
Die Installation von libcurl hängt von Ihrem Betriebssystem ab:
# Ubuntu/Debiansudo apt-get install libcurl4-openssl-dev
# macOS (über Homebrew)brew install curl
# Windows (über vcpkg)vcpkg install curlEinfache GET-Anfrage mit libcurl
Beginnen wir mit einem grundlegenden Beispiel – Senden einer GET-Anfrage und Empfangen der Antwort:
#include <iostream>#include <curl/curl.h>#include <string>
// Callback-Funktion zum Schreiben von Datensize_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 << "Fehler bei der CURL-Initialisierung" << 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 << "Anfragefehler: " << curl_easy_strerror(res) << std::endl; } else { std::cout << "Serverantwort:" << std::endl; std::cout << response << std::endl; } curl_easy_cleanup(curl); return 0;}Senden einer POST-Anfrage mit Daten
POST-Anfragen werden verwendet, um Daten an den Server zu senden. Betrachten wir ein Beispiel mit JSON-Daten:
#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_