Skip to content

Основные концепции

Понимание этих концепций позволяет быстро составить ментальную модель HTTPC.

Двухслойная архитектура API

HTTPC предлагает два эквивалентных способа выполнения запросов, соответствующих разделению net/http на http.Get и http.Client:

Пакетные функции — нулевая настройка, поддерживаются лениво инициализируемым клиентом по умолчанию. Подходят для скриптов и разовых запросов:

go
result, err := httpc.Get("https://api.example.com/data")

Экземпляр Client — полный контроль над конфигурацией, пулом соединений и жизненным циклом. Подходит для долго работающих сервисов:

go
client, err := httpc.NewDefault()
defer func() { _ = client.Close() }()
result, err := client.Get("https://api.example.com/data")

Оба слоя принимают одинаковые опции запроса (WithHeader, WithJSON…) и возвращают одинаковый тип *Result. Пакетные функции — тонкие обёртки над одноэлементным клиентом.

Что выбрать?

Разовые запросы или быстрые прототипы → пакетные функции. Продакшен-сервисы, кастомная конфигурация или управление пулом соединений → экземпляр Client.

Конфигурация: Config и опции With*

HTTPC разделяет конфигурацию на два независимых слоя:

СлойНосительОбластьТипичные поля
Конфигурация экземпляраСтруктура ConfigВесь жизненный цикл клиентаТаймауты, политика повторов, пул соединений, TLS
Опции запросаФункции WithXxx()Один запросWithHeader, WithJSON, WithTimeout

Конфигурация экземпляра передаётся в New() через структуру Config. Начните с DefaultConfig() и изменяйте поля по необходимости:

go
cfg := httpc.DefaultConfig()
cfg.Timeouts.Request = 60 * time.Second
cfg.Retry.MaxRetries = 5
client, err := httpc.New(cfg)

Опции запроса передаются при каждом вызове, дополняя или переопределяя значения уровня экземпляра:

go
result, err := client.Get(url,
    httpc.WithHeader("Authorization", "Bearer "+token),
    httpc.WithTimeout(30*time.Second),
)

Пресет-конфигурации (SecureConfig(), PerformanceConfig() и др.) также доступны как отправные точки. См. Config API.

Жизненный цикл запроса

Каждый запрос проходит через следующий конвейер:

text
Применение опций → Цепочка middleware (если есть) → Выполнение движка → Повтор (если нужно) → Result возвращён
      ↑                                         ↑
   With* функции              Пул соединений / TLS / Прокси / SSRF-проверки
  • Применение опций — функции With* задают заголовки, тело, таймаут и т.д.
  • Цепочка middleware — кастомный логгинг, метрики, аудит (настраивается через Config.Middleware)
  • Выполнение движка — переиспользование пула соединений, TLS-рукопожатие, HTTP/2-согласование, SSRF-валидация
  • Повтор — автоматический экспоненциальный откат при повторимых ошибках (таймауты, 5xx, 429 и др.)
  • Result — содержит данные ответа, метаданные запроса и статистику повторов; управляется GC, ручное освобождение не требуется

Безопасные значения по умолчанию

HTTPC безопасен по умолчанию — без дополнительной конфигурации обеспечивает:

  • TLS 1.2+ принудительное шифрование
  • SSRF-защита — блокировка соединений к приватным/зарезервированным IP-адресам (127.0.0.1, 10.x, 192.168.x и др.)
  • Предотвращение CRLF-инъекций — автоматическая валидация заголовков и URL
  • Ограничение размера тела ответа — 10 МБ по умолчанию, предотвращает исчерпание памяти

Для подключения к внутренним сервисам (VPN, интранет) установите Security.AllowPrivateIPs = true или используйте SSRFExemptCIDRs для выборочного разрешения. См. Обзор безопасности.

Модель ошибок

HTTPC различает ошибки сетевого уровня и HTTP-коды состояния:

  • Сетевые ошибки (сбои соединения, таймауты, ошибки TLS) → возвращаются как error; используйте errors.As для извлечения ClientError и получения классификации и повторимости
  • HTTP-коды состояния (4xx, 5xx) → не возвращаются как error; проверяются через result.IsSuccess() и аналогичные методы
go
result, err := client.Get(url)
if err != nil {
    // Сетевая ошибка — запрос не завершён успешно
    var clientErr *httpc.ClientError
    if errors.As(err, &clientErr) {
        log.Printf("Тип ошибки: %s, повторимо: %v", clientErr.Code(), clientErr.IsRetryable())
    }
    return err
}
// Запрос завершён — проверка HTTP-кода состояния
if !result.IsSuccess() {
    log.Printf("HTTP-ошибка: %d", result.StatusCode())
}

См. Обработка ошибок.