HTTP клиент на C++: делаем запросы правильно от А до Я

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

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;
}

Блоги

Рекомендаций по книгам