HTTP клиент на C++: делаем запросы правильно от А до Я
В современном мире программирования взаимодействие с удаленными серверами через HTTP протокол является одной из базовых задач. Будь то получение данных с API, отправка формы или загрузка файла — умение работать с HTTP запросами необходимо каждому C++ разработчику. В этой статье мы разберем, как создать полноценный HTTP клиент на C++, рассмотрим популярные библиотеки и лучшие практики.
Зачем нужен HTTP клиент на C++?
В отличие от языков с встроенными HTTP библиотеками (Python, JavaScript), C++ не имеет стандартного инструмента для работы с HTTP в стандартной библиотеке. Однако это не проблема, так как существует несколько мощных и проверенных временем решений:
- libcurl — самая популярная и мощная библиотека для работы с URL
- cpprestsdk (Casablanca) — современная асинхронная библиотека от Microsoft
- Boost.Beast — библиотека на основе Boost.Asio для низкоуровневой работы
В этой статье мы сосредоточимся на libcurl и cpprestsdk, как на наиболее часто используемых решениях.
Основы работы с libcurl
libcurl — это проверенная временем библиотека, которая поддерживает множество протоколов, включая HTTP/1.1, HTTP/2, FTP и другие. Она написана на C, но имеет отличные биндинги для C++.
Установка libcurl
Установка libcurl зависит от вашей операционной системы:
# Ubuntu/Debian
sudo apt-get install libcurl4-openssl-dev
# macOS (через Homebrew)
brew install curl
# Windows (через vcpkg)
vcpkg install curl
Простой GET запрос с libcurl
Начнем с базового примера — отправка GET запроса и получение ответа:
#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) {
std::cerr << "Ошибка инициализации 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 << "Ошибка запроса: " << curl_easy_strerror(res) << std::endl;
} else {
std::cout << "Ответ сервера:" << std::endl;
std::cout << response << std::endl;
}
curl_easy_cleanup(curl);
return 0;
}
Отправка POST запроса с данными
POST запросы используются для отправки данных на сервер. Рассмотрим пример с 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_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &response);
CURLcode res = curl_easy_perform(curl);
if (res == CURLE_OK) {
long http_code = 0;
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &http_code);
std::cout << "HTTP код: " << http_code << std::endl;
std::cout << "Ответ: " << response << std::endl;
}
curl_slist_free_all(headers);
curl_easy_cleanup(curl);
return 0;
}
Современный подход: cpprestsdk (Casablanca)
cpprestsdk — это асинхронная библиотека от Microsoft, которая предоставляет более современный C++ интерфейс с поддержкой PPL (Parallel Patterns Library) и JSON.
Установка cpprestsdk
# Ubuntu/Debian
sudo apt-get install libcpprest-dev
# macOS
brew install cpprestsdk
# Windows (через vcpkg)
vcpkg install cpprestsdk cpprestsdk:x64-windows
Асинхронный GET запрос
#include <iostream>
#include <cpprest/http_client.h>
#include <cpprest/filestream.h>
using namespace web;
using namespace web::http;
using namespace web::http::client;
int main() {
// Создаем HTTP клиент
http_client client(U("https://jsonplaceholder.typicode.com"));
// Отправляем GET запрос
client.request(methods::GET, U("/posts/1"))
.then([](http_response response) {
std::cout << "Статус: " << response.status_code() << std::endl;
return response.extract_json();
})
.then([](json::value jsonData) {
std::cout << "ID: " << jsonData[U("id")].as_integer() << std::endl;
std::cout << "Заголовок: " << jsonData[U("title")].as_string() << std::endl;
})
.wait(); // Ждем завершения асинхронной операции
return 0;
}