Introducción: ¿por qué escribir un cliente HTTP en C++?
En el desarrollo moderno, la interacción con servicios web se ha convertido en una parte integral de prácticamente cualquier aplicación. Incluso si estás escribiendo un programa de escritorio en C++, tarde o temprano necesitarás enviar datos a un servidor u obtenerlos de él. A diferencia de los lenguajes de scripting, C++ no tiene herramientas integradas para trabajar con HTTP, pero eso no es un problema. Existen varias formas probadas de implementar un cliente HTTP en C++, y las analizaremos de lo simple a lo complejo.
En este artículo, veremos:
- Cómo usar la biblioteca libcurl — el estándar de oro para trabajar con HTTP en C++
- Cómo enviar solicitudes GET y POST con cabeceras y cuerpo
- Cómo procesar la respuesta recibida y analizar JSON
- Cómo evitar errores típicos al trabajar con solicitudes de red
Todos los ejemplos de código se pueden usar directamente en tus proyectos. ¡Vamos allá!
1. Elección de la biblioteca: libcurl como herramienta principal
Escribir un cliente HTTP en C++ desde cero es una tarea ingrata. Tendrías que trabajar con sockets, formar cabeceras manualmente, analizar respuestas y manejar un montón de casos extremos. Afortunadamente, existe libcurl — una biblioteca potente, estable y multiplataforma que hace todo el trabajo sucio por ti.
Para empezar, instala libcurl. En Ubuntu se hace con un solo comando:
sudo apt-get install libcurl4-openssl-devEn Windows puedes usar vcpkg o descargar binarios precompilados. Después de la instalación, enlaza la biblioteca en tu CMakeLists.txt o simplemente enlázala manualmente con las banderas -lcurl.
La estructura básica de trabajo con libcurl es siempre la misma:
- Inicializamos el contexto global con la llamada
curl_global_init() - Creamos un descriptor de sesión
curl_easy_init() - Establecemos los parámetros de la solicitud (URL, cabeceras, método, etc.)
- Ejecutamos la solicitud
curl_easy_perform() - Liberamos los recursos
¿Suena simple? Pasemos al código.
2. Envío de solicitudes GET y POST: ejemplos prácticos
2.1 Solicitud GET simple
Empecemos con lo clásico: obtengamos datos de una API pública. Supongamos que queremos saber el tipo de cambio actual de Bitcoin a dólar:
#include <iostream>#include <string>#include <curl/curl.h>
// Función callback para escribir datos en una cadenastatic size_t WriteCallback(void* contents, size_t size, size_t nmemb, void* userp) { ((std::string*)userp)->append((char*)contents, size * nmemb); return size * nmemb;}
int main() { curl_global_init(CURL_GLOBAL_DEFAULT); CURL* curl = curl_easy_init(); std::string response; if (curl) { curl_easy_setopt(curl, CURLOPT_URL, "https://api.coindesk.com/v1/bpi/currentprice.json"); 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: " << curl_easy_strerror(res) << std::endl; } else { std::cout << "Respuesta del servidor:" << response << std::endl; } curl_easy_cleanup(curl); } curl_global_cleanup(); return 0;}Observa la función callback WriteCallback. libcurl no sabe dónde guardar los datos, por lo que pasamos un puntero a una cadena y escribimos en ella a medida que llegan los datos. Este es un patrón estándar.
2.2 Solicitud POST con cuerpo JSON
Ahora enviemos datos al servidor. Supongamos que estamos registrando un usuario:
#include <iostream>#include <string>#include <curl/curl.h>
int main() { curl_global_init(CURL_GLOBAL_DEFAULT); CURL* curl =