Cliente HTTP en C++: haciendo solicitudes correctamente de la A a la Z
\n\nEn el mundo moderno del desarrollo de software, la capacidad de interactuar con servidores remotos a través de HTTP es una habilidad básica. Ya sea para descargar datos de una API, enviar formularios o trabajar con servicios web, C++ proporciona varias herramientas potentes para crear clientes HTTP. En este artículo, analizaremos cómo hacer solicitudes HTTP correctamente en C++, revisaremos bibliotecas populares y escribiremos ejemplos de código funcionales.
\n\n¿Por qué C++ para solicitudes HTTP?
\n\nC++ no tiene soporte integrado para HTTP en la biblioteca estándar, a diferencia de Python o JavaScript. Sin embargo, esto no es un problema: existen bibliotecas probadas a lo largo del tiempo que permiten enviar solicitudes de manera fácil y eficiente. Las opciones principales son:
\n\n- \n
- libcurl (cURL) — la biblioteca multiplataforma más popular. \n
- Boost.Beast — una biblioteca moderna basada en Boost.Asio. \n
- WinHTTP — una solución integrada para Windows. \n
- Qt Network — para proyectos en Qt. \n
En este artículo nos centraremos en las dos primeras, ya que son las más versátiles y adecuadas para la mayoría de las tareas.
\n\n1. Cliente HTTP usando libcurl
\n\nlibcurl es una biblioteca probada durante años que soporta HTTP, HTTPS, FTP y muchos otros protocolos. Es fácil de usar y está excelentemente documentada.
\n\nInstalación de libcurl
\n\nPara Linux (Ubuntu/Debian):
\nsudo apt-get install libcurl4-openssl-dev\n\nPara Windows, puede descargar archivos binarios precompilados del sitio oficial curl.se o usar vcpkg:
\nvcpkg install curl\n\nSolicitud GET simple
\n\nEscribamos un ejemplo básico para obtener datos de un servidor:
\n\n#include <iostream>\n#include <string>\n#include <curl/curl.h>\n\n// Función de devolución de llamada para escribir datos\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 << "Error de inicialización de CURL" << 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); // Desactivar verificación SSL para prueba\n\n CURLcode res = curl_easy_perform(curl);\n if (res != CURLE_OK) {\n std::cerr << "Error de solicitud: " << curl_easy_strerror(res) << std::endl;\n } else {\n std::cout << "Respuesta del servidor:\\n" << response << std::endl;\n }\n\n curl_easy_cleanup(curl);\n return 0;\n}\n\nSe debe compilar con la bandera -lcurl:
g++ -o http_client http_client.cpp -lcurl\n\nSolicitud POST con envío de JSON
\n\nAhora agreguemos el envío de datos:
\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