Cliente HTTP en C++: haciendo solicitudes correctamente de la A a la Z
En el mundo moderno de la programación, la interacción con servidores remotos a través del protocolo HTTP es una de las tareas básicas. Ya sea obtener datos de una API, enviar un formulario o descargar un archivo, saber trabajar con solicitudes HTTP es necesario para todo desarrollador de C++. En este artículo, analizaremos cómo crear un cliente HTTP completo en C++, revisaremos bibliotecas populares y las mejores prácticas.
¿Por qué necesito un cliente HTTP en C++?
A diferencia de los lenguajes con bibliotecas HTTP integradas (Python, JavaScript), C++ no tiene una herramienta estándar para trabajar con HTTP en la biblioteca estándar. Sin embargo, esto no es un problema, ya que existen varias soluciones potentes y probadas a lo largo del tiempo:
- libcurl — la biblioteca más popular y potente para trabajar con URL
- cpprestsdk (Casablanca) — una biblioteca asíncrona moderna de Microsoft
- Boost.Beast — una biblioteca basada en Boost.Asio para trabajo de bajo nivel
En este artículo, nos centraremos en libcurl y cpprestsdk, como las soluciones más utilizadas.
Fundamentos del trabajo con libcurl
libcurl es una biblioteca probada a lo largo del tiempo que admite múltiples protocolos, incluyendo HTTP/1.1, HTTP/2, FTP y otros. Está escrita en C, pero tiene excelentes enlaces para C++.
Instalación de libcurl
La instalación de libcurl depende de su sistema operativo:
# Ubuntu/Debiansudo apt-get install libcurl4-openssl-dev
# macOS (a través de Homebrew)brew install curl
# Windows (a través de vcpkg)vcpkg install curlSolicitud GET simple con libcurl
Comencemos con un ejemplo básico: enviar una solicitud GET y recibir la respuesta:
#include <iostream>#include <curl/curl.h>#include <string>
// Función de devolución de llamada para escribir datossize_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 << "Error de inicialización de CURL" << 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 << "Error de solicitud: " << curl_easy_strerror(res) << std::endl; } else { std::cout << "Respuesta del servidor:" << std::endl; std::cout << response << std::endl; } curl_easy_cleanup(curl); return 0;}Envío de una solicitud POST con datos
Las solicitudes POST se utilizan para enviar datos al servidor. Veamos un ejemplo con datos JSON:
#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_