Cliente HTTP em C++: fazendo requisições corretamente do A ao Z
No mundo moderno da programação, a interação com servidores remotos através do protocolo HTTP é uma das tarefas básicas. Seja para obter dados de uma API, enviar um formulário ou baixar um arquivo — saber trabalhar com requisições HTTP é necessário para todo desenvolvedor C++. Neste artigo, vamos analisar como criar um cliente HTTP completo em C++, explorar bibliotecas populares e as melhores práticas.
Por que um cliente HTTP em C++?
Ao contrário de linguagens com bibliotecas HTTP embutidas (Python, JavaScript), o C++ não possui uma ferramenta padrão para trabalhar com HTTP na biblioteca padrão. No entanto, isso não é um problema, pois existem várias soluções poderosas e testadas pelo tempo:
- libcurl — a biblioteca mais popular e poderosa para trabalhar com URLs
- cpprestsdk (Casablanca) — uma biblioteca assíncrona moderna da Microsoft
- Boost.Beast — biblioteca baseada em Boost.Asio para trabalho de baixo nível
Neste artigo, vamos nos concentrar no libcurl e no cpprestsdk, como as soluções mais frequentemente utilizadas.
Fundamentos do trabalho com libcurl
libcurl é uma biblioteca testada pelo tempo que suporta vários protocolos, incluindo HTTP/1.1, HTTP/2, FTP e outros. Ela é escrita em C, mas possui ótimas bindings para C++.
Instalação do libcurl
A instalação do libcurl depende do seu sistema operacional:
# Ubuntu/Debiansudo apt-get install libcurl4-openssl-dev
# macOS (via Homebrew)brew install curl
# Windows (via vcpkg)vcpkg install curlRequisição GET simples com libcurl
Vamos começar com um exemplo básico — enviar uma requisição GET e obter a resposta:
#include <iostream>#include <curl/curl.h>#include <string>
// Função de callback para escrever dadossize_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 << "Erro de inicialização do 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 << "Erro na requisição: " << curl_easy_strerror(res) << std::endl; } else { std::cout << "Resposta do servidor:" << std::endl; std::cout << response << std::endl; } curl_easy_cleanup(curl); return 0;}Envio de requisição POST com dados
Requisições POST são usadas para enviar dados para o servidor. Vamos ver um exemplo com dados 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_