Introdução: Por que Escrever um Cliente HTTP em C++?
No desenvolvimento moderno, interagir com serviços web tornou-se parte integrante de praticamente qualquer aplicação. Mesmo que você esteja escrevendo um programa desktop em C++, mais cedo ou mais tarde precisará enviar dados para um servidor ou recebê-los de lá. Diferente de linguagens de script, C++ não possui ferramentas nativas para trabalhar com HTTP — mas isso não é um problema. Existem várias formas comprovadas de implementar um cliente HTTP em C++, e vamos analisá-las do simples ao complexo.
Neste artigo, abordaremos:
- Como usar a biblioteca libcurl — o padrão ouro para trabalhar com HTTP em C++
- Como enviar requisições GET e POST com cabeçalhos e corpo
- Como processar a resposta recebida e fazer parse de JSON
- Como evitar erros comuns ao trabalhar com requisições de rede
Todos os exemplos de código podem ser usados imediatamente em seus projetos. Vamos lá!
1. Escolhendo uma Biblioteca: libcurl como Ferramenta Principal
Escrever um cliente HTTP em C++ do zero é uma tarefa ingrata. Você terá que trabalhar com sockets, formar cabeçalhos manualmente, fazer parse de respostas e lidar com vários casos extremos. Felizmente, existe o libcurl — uma biblioteca poderosa, estável e multiplataforma que faz todo o trabalho pesado para você.
Para começar, instale o libcurl. No Ubuntu, isso é feito com um comando:
sudo apt-get install libcurl4-openssl-devNo Windows, você pode usar o vcpkg ou baixar binários pré-compilados. Após a instalação, vincule a biblioteca no seu CMakeLists.txt ou simplesmente vincule manualmente com as flags -lcurl.
A estrutura básica de trabalho com o libcurl é sempre a mesma:
- Inicialize o contexto global chamando
curl_global_init() - Crie um handle de sessão
curl_easy_init() - Defina os parâmetros da requisição (URL, cabeçalhos, método, etc.)
- Execute a requisição
curl_easy_perform() - Limpe os recursos
Parece simples? Vamos para o código.
2. Enviando Requisições GET e POST: Exemplos Práticos
2.1 Requisição GET Simples
Vamos começar com um clássico — obter dados de uma API pública. Suponha que queremos saber a cotação atual do Bitcoin em Dólar:
#include <iostream>#include <string>#include <curl/curl.h>
// Função callback para escrever dados em uma stringstatic 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 << "Server response:" << response << std::endl; } curl_easy_cleanup(curl); } curl_global_cleanup(); return 0;}Observe a função callback WriteCallback. O libcurl não sabe onde salvar os dados, então passamos um ponteiro para uma string e escrevemos nela à medida que os dados chegam. Este é um padrão padrão.
2.2 Requisição POST com Corpo JSON
Agora vamos enviar dados para o servidor. Suponha que estamos registrando um usuário:
#include <iostream>#include <string>#include <curl/curl.h>
int main() { curl_global_init(CURL_GLOBAL_DEFAULT); CURL* curl