> Можно ли указать кастомный заголовок в HTTP запросе (Go)

Уровень: senior · Роль: backend · Язык: Go · Категория: Технические вопросы

Компании: Wildberries

Стек: Go

> Пример ответа

Короткий ответ

Да, в Go можно указать кастомный заголовок в HTTP-запросе. Для этого используется структура http.Header - map типа map[string][]string, где ключ - имя заголовка, значение - срез строк. Заголовки задаются через метод Header.Set() или Header.Add() перед отправкой запроса. Важно помнить, что некоторые заголовки (например, Host) управляются отдельно через поля структуры http.Request.

Подробное объяснение

В Go работа с HTTP-заголовками строится вокруг типа http.Header. Это обычная map, но с методами-хелперами: Set, Add, Get, Del. При создании запроса через http.NewRequest заголовки уже инициализированы, но пусты - можно сразу добавлять свои.

Ключевые моменты:

  • Header.Set(key, value) - заменяет все значения заголовка одним. Имя заголовка нормализуется (например, content-type станет Content-Type).
  • Header.Add(key, value) - добавляет значение к существующим. Это важно для заголовков, которые могут повторяться (например, Cookie или X-Forwarded-For).
  • Значение заголовка - всегда строка. Числа и другие типы нужно конвертировать через strconv.
  • Для кастомных заголовков принято использовать префикс X-, хотя это не обязательное требование - просто соглашение.
  • Некоторые заголовки управляются не через Header, а через поля структуры http.Request: Host, ContentLength, TransferEncoding. Например, Host нельзя задать через Header.Set("Host", ...) - нужно присвоить req.Host.

При отправке запроса через http.Client.Do заголовки сериализуются в wire format. Go сам обрабатывает валидацию: запрещает некоторые символы в именах и значениях, добавляет обязательные заголовки (например, Content-Length для тела).

На практике

На практике кастомные заголовки нужны для:

  • аутентификации (например, X-API-Key или Authorization - но последний часто задают через Header.Set);
  • передачи trace-информации (X-Request-ID, X-Correlation-ID);
  • указания версии API (X-API-Version);
  • кастомных метаданных для внутренних сервисов.

Важно помнить, что при работе с http.Client заголовки не переиспользуются между запросами - каждый запрос создаётся заново. Если нужно задать одинаковые заголовки для многих запросов, можно использовать middleware или обёртку над http.RoundTripper.

Также стоит учитывать, что некоторые прокси и серверы могут игнорировать или перезаписывать определённые заголовки (например, X-Forwarded-*). Это не проблема Go, а особенность инфраструктуры.

Пример кода

GO
package main
import (
"context"
"fmt"
"net/http"
"time"
)
func main() {
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
req, err := http.NewRequestWithContext(ctx, http.MethodGet, "https://api.example.com/data", nil)
if err != nil {
panic(err)
}
// Кастомные заголовки
req.Header.Set("X-API-Key", "secret-key-123")
req.Header.Set("X-Request-ID", "req-abc-123")
req.Header.Add("X-Trace", "span-1")
req.Header.Add("X-Trace", "span-2") // добавит второе значение
// Заголовок Host задаётся отдельно
req.Host = "custom.host.example"
client := &http.Client{Timeout: 10 * time.Second}
resp, err := client.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
fmt.Println("Status:", resp.Status)
}

Как отвечать на собеседовании

Начни с прямого ответа - да, можно. Затем покажи знание структуры http.Header и методов Set/Add. Обязательно упомяни разницу между ними: Set заменяет, Add добавляет. Хорошо, если вспомнишь про Host - это показывает понимание внутреннего устройства http.Request.

Дальше можно рассказать про нормализацию имён заголовков и про то, что Go сам валидирует заголовки при отправке. Если спросят про безопасность - упомяни, что нельзя подделать некоторые заголовки на уровне клиента (например, Content-Length), потому что Go пересчитывает их автоматически.

Для уровня senior стоит добавить про http.RoundTripper и middleware - как переиспользовать заголовки между запросами. Также можно упомянуть про контекст и таймауты, если это уместно в разговоре.

Что проверяет интервьюер

Интервьюер проверяет:

  • базовое знание стандартной библиотеки net/http;
  • понимание разницы между Set и Add;
  • знание ограничений (например, Host);
  • умение работать с заголовками в реальном коде;
  • для senior - понимание жизненного цикла запроса и возможность расширения через middleware.

Если кандидат сразу говорит про Header.Set и приводит пример - это хорошо. Если ещё и упоминает RoundTripper - отлично.

Типичные ошибки

  • Попытка задать Host через Header.Set("Host", ...) - не сработает, нужно req.Host.
  • Использование Header.Set для заголовков, которые должны повторяться - теряются предыдущие значения.
  • Забывают про контекст и таймауты - запрос может зависнуть.
  • Не проверяют ошибку от http.NewRequest - паника в production-коде.
  • Путают Header и Trailer - trailer-заголовки отправляются после тела, это отдельная механика.
  • Пытаются задать заголовок с недопустимыми символами - Go вернёт ошибку при отправке, но не при создании запроса.

> ГОТОВЫ К СЛЕДУЮЩЕМУ СОБЕСЕДОВАНИЮ?

Запустите тренировочную сессию с ИИ и получите детальную обратную связь, чтобы увереннее проходить реальные интервью