← Назад к вопросам

Что такое libcurl?

1.0 Junior🔥 231 комментариев
#Сети и протоколы

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI29 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Что такое libcurl?

libcurl — это мощная открытая библиотека для создания HTTP/HTTPS запросов в C и C++ приложениях. Я имею глубокий опыт работы с ней в production системах.

Что такое libcurl

libcurl (URL Transfer Library) — это кросс-платформенная библиотека для:
  • Загрузки и отправки данных по различным протоколам
  • Работы с HTTP, HTTPS, FTP, SFTP и другими
  • Управления кукиз, авторизацией, редиректами
  • Асинхронной обработки сетевых запросов

Поддерживает: Linux, Windows, macOS, Android, iOS и другие ОС.

Протоколы

libcurl поддерживает:

  • HTTP/0.9, HTTP/1.0, HTTP/1.1, HTTP/2, HTTP/3 — веб
  • HTTPS — защищённый веб
  • FTP/FTPS — файловые сервера
  • SFTP — SSH file transfer
  • SCP — Secure copy
  • TELNET — удалённый терминал
  • LDAP/LDAPS — directory services
  • Многое другое

Установка

На Linux:

# Ubuntu/Debian
sudo apt-get install libcurl4-openssl-dev

# RHEL/CentOS
sudo yum install curl-devel

# Arch
sudo pacman -S curl

На macOS:

brew install curl

Базовый пример

#include <iostream>
#include <curl/curl.h>
#include <string>

// Callback для обработки ответа
static size_t WriteCallback(void* contents, size_t size, size_t nmemb, std::string* s)
{
    size_t newLength = size * nmemb;
    s->append((char*)contents, newLength);
    return newLength;
}

int main()
{
    CURL* curl = curl_easy_init();
    
    if (curl) {
        std::string readBuffer;
        
        // Устанавливаем URL
        curl_easy_setopt(curl, CURLOPT_URL, "https://api.example.com/users");
        
        // Устанавливаем callback для получения данных
        curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback);
        curl_easy_setopt(curl, CURLOPT_WRITEDATA, &readBuffer);
        
        // Таймаут
        curl_easy_setopt(curl, CURLOPT_TIMEOUT, 10L);
        
        // Выполняем запрос
        CURLcode res = curl_easy_perform(curl);
        
        if (res != CURLE_OK) {
            std::cerr << "Ошибка: " << curl_easy_strerror(res) << std::endl;
        } else {
            std::cout << "Ответ: " << readBuffer << std::endl;
        }
        
        // Очищаем
        curl_easy_cleanup(curl);
    }
    
    return 0;
}

Компиляция:

g++ -o example example.cpp -lcurl
./example

POST запрос с JSON

#include <curl/curl.h>
#include <iostream>
#include <string>

static size_t WriteCallback(void* contents, size_t size, size_t nmemb, std::string* s)
{
    s->append((char*)contents, size * nmemb);
    return size * nmemb;
}

int main()
{
    CURL* curl = curl_easy_init();
    
    if (curl) {
        std::string readBuffer;
        std::string postData = R"({"name": "John", "email": "john@example.com"})";
        
        struct curl_slist* headers = nullptr;
        headers = curl_slist_append(headers, "Content-Type: application/json");
        
        curl_easy_setopt(curl, CURLOPT_URL, "https://api.example.com/users");
        curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
        curl_easy_setopt(curl, CURLOPT_POSTFIELDS, postData.c_str());
        curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback);
        curl_easy_setopt(curl, CURLOPT_WRITEDATA, &readBuffer);
        
        CURLcode res = curl_easy_perform(curl);
        
        if (res != CURLE_OK) {
            std::cerr << "Ошибка: " << curl_easy_strerror(res) << std::endl;
        } else {
            long response_code;
            curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response_code);
            std::cout << "HTTP Code: " << response_code << std::endl;
            std::cout << "Response: " << readBuffer << std::endl;
        }
        
        curl_slist_free_all(headers);
        curl_easy_cleanup(curl);
    }
    
    return 0;
}

Основные опции (curl_easy_setopt)

URL и Метод:

curl_easy_setopt(curl, CURLOPT_URL, "https://api.example.com");
curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "PUT");

Заголовки:

struct curl_slist* headers = nullptr;
headers = curl_slist_append(headers, "Authorization: Bearer token123");
headers = curl_slist_append(headers, "X-Custom-Header: value");
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);

Авторизация:

// Basic auth
curl_easy_setopt(curl, CURLOPT_USERPWD, "user:password");

// Bearer token
curl_easy_setopt(curl, CURLOPT_HTTPAUTH, CURLAUTH_BEARER);
curl_easy_setopt(curl, CURLOPT_XOAUTH2_BEARER, "token");

SSL/TLS:

// Отключить проверку сертификата (только для разработки!)
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);

// Использовать конкретный сертификат
curl_easy_setopt(curl, CURLOPT_CAINFO, "/path/to/ca-bundle.crt");

Таймауты:

curl_easy_setopt(curl, CURLOPT_TIMEOUT, 30L);           // 30 сек
curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 10L);   // 10 сек на подключение

Редирект:

curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);    // Следить редиректам
curl_easy_setopt(curl, CURLOPT_MAXREDIRS, 5L);          // Максимум 5 редиректов

Кукиз:

curl_easy_setopt(curl, CURLOPT_COOKIEFILE, "cookies.txt");
curl_easy_setopt(curl, CURLOPT_COOKIEJAR, "cookies.txt");

Proxy:

curl_easy_setopt(curl, CURLOPT_PROXY, "proxy.example.com:8080");
curl_easy_setopt(curl, CURLOPT_PROXYAUTH, CURLAUTH_BASIC);
curl_easy_setopt(curl, CURLOPT_PROXYUSERPWD, "user:password");

Вывод информации о запросе

long response_code;
char* effective_url = nullptr;
struct curl_slist* cookies = nullptr;

curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response_code);
curl_easy_getinfo(curl, CURLINFO_EFFECTIVE_URL, &effective_url);
curl_easy_getinfo(curl, CURLINFO_COOKIELIST, &cookies);

std::cout << "Response code: " << response_code << std::endl;
std::cout << "Final URL: " << effective_url << std::endl;

Загрузка файла

FILE* file = fopen("image.jpg", "rb");

curl_easy_setopt(curl, CURLOPT_URL, "https://upload.example.com");
curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L);
curl_easy_setopt(curl, CURLOPT_READDATA, file);

CURLcode res = curl_easy_perform(curl);

fclose(file);

Асинхронные запросы с curl_multi

CURLM* multi_handle = curl_multi_init();

// Добавляем несколько запросов
CURL* curl1 = curl_easy_init();
CURL* curl2 = curl_easy_init();
CURL* curl3 = curl_easy_init();

curl_easy_setopt(curl1, CURLOPT_URL, "https://api.example.com/1");
curl_easy_setopt(curl2, CURLOPT_URL, "https://api.example.com/2");
curl_easy_setopt(curl3, CURLOPT_URL, "https://api.example.com/3");

curl_multi_add_handle(multi_handle, curl1);
curl_multi_add_handle(multi_handle, curl2);
curl_multi_add_handle(multi_handle, curl3);

int still_running = 1;
while (still_running) {
    curl_multi_perform(multi_handle, &still_running);
    // Можем делать что-то ещё пока запросы обрабатываются
}

curl_multi_remove_handle(multi_handle, curl1);
curl_multi_remove_handle(multi_handle, curl2);
curl_multi_remove_handle(multi_handle, curl3);
curl_multi_cleanup(multi_handle);

Best Practices

  1. Всегда проверяй return код — curl_easy_perform может упасть
  2. Используй таймауты — не жди бесконечно
  3. Обработка ошибок — curl_easy_strerror для читаемых сообщений
  4. Очистка памяти — curl_easy_cleanup, curl_slist_free_all
  5. SSL сертификаты — проверяй в production, не отключай
  6. Переиспользуй handles — создание CURL handle дорого
  7. Логирование — используй CURLOPT_VERBOSE для отладки

Практическое применение в Backend

Я использовал libcurl для:

  • Интеграции с внешними API (платёжные системы, облачные сервисы)
  • Вебхуков и callback уведомлений
  • Кэширования данных из третьих источников
  • Микросервис коммуникации
  • Здоровья проверки (health checks) внешних сервисов

libcurl — это стандартный инструмент в C/C++ backend разработке, незаменим при работе с HTTP.

Что такое libcurl? | PrepBro