Как установить заголовки (headers) в HTTP GET запросе на Go?
Правильный способ установки заголовков в GET-запросе на Go
Ваш подход в целом верный, но есть несколько важных нюансов, которые нужно учесть. Давайте разберем все по порядку.
Базовый шаблон — это использование http.NewRequest и установка заголовков через req.Header.Set():
package main
import (
"fmt"
"io"
"net/http"
)
func main() {
// Создаем новый GET-запрос
req, err := http.NewRequest("GET", "https://api.example.com/data", nil)
if err != nil {
fmt.Println("Ошибка при создании запроса:", err)
return
}
// Устанавливаем заголовки
req.Header.Set("Authorization", "Bearer my-token")
req.Header.Set("Accept", "application/json")
req.Header.Set("User-Agent", "MyApp/1.0")
// Создаем HTTP-клиент (можно с таймаутом)
client := &http.Client{}
// Выполняем запрос
resp, err := client.Do(req)
if err != nil {
fmt.Println("Ошибка при выполнении запроса:", err)
return
}
defer resp.Body.Close()
// Читаем тело ответа
body, err := io.ReadAll(resp.Body)
if err != nil {
fmt.Println("Ошибка при чтении ответа:", err)
return
}
fmt.Println("Статус:", resp.Status)
fmt.Println("Тело ответа:", string(body))
}
Важные моменты:
- Проверка ошибок: Всегда проверяйте ошибки при создании запроса и выполнении
client.Do(). - Закрытие тела ответа: Используйте
defer resp.Body.Close()сразу после проверки ошибки, чтобы избежать утечки ресурсов. - Множественные заголовки: Если нужно установить несколько значений для одного заголовка (например,
Set-Cookie), используйтеreq.Header.Add()вместоSet().Set()заменяет предыдущее значение, аAdd()добавляет новое.
Установка таймаута для клиента
Для production-кода рекомендуется устанавливать таймаут, чтобы запрос не зависал:
client := &http.Client{
Timeout: 10 * time.Second,
}
Использование контекста (Context)
Для отмены запроса или установки дедлайна используйте context.Context:
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
req, err := http.NewRequestWithContext(ctx, "GET", "https://api.example.com/data", nil)
req.Header.Set("Authorization", "Bearer my-token")
resp, err := client.Do(req)
Альтернатива: использование RoundTripper
Если вам нужно добавлять заголовки ко всем запросам (например, для всех API-запросов), можно создать свой транспорт:
type AuthTransport struct {
Token string
}
func (t *AuthTransport) RoundTrip(req *http.Request) (*http.Response, error) {
req.Header.Set("Authorization", "Bearer "+t.Token)
return http.DefaultTransport.RoundTrip(req)
}
client := &http.Client{
Transport: &AuthTransport{Token: "my-token"},
}
resp, err := client.Get("https://api.example.com/data")
Таким образом, ваш изначальный подход абсолютно правильный. Главное — не забывать про обработку ошибок и закрытие тела ответа. Удачи!
<<Упрощенный подход с использованием http.Get и обертки
Если вам не нужна полная гибкость http.NewRequest, можно создать небольшую функцию-обертку, которая добавляет заголовки к стандартному http.Get:
func GetWithHeaders(url string, headers map[string]string) (*http.Response, error) {
req, err := http.NewRequest("GET", url, nil)
if err != nil {
return nil, err
}
for key, value := range headers {
req.Header.Set(key, value)
}
client := &http.Client{}
return client.Do(req)
}
// Использование:
headers := map[string]string{
"Authorization": "Bearer my-token",
"Accept": "application/json",
}
resp, err := GetWithHeaders("https://api.example.com/data", headers)
Использование сторонних библиотек
Для более сложных сценариев (например, автоматическое обновление токенов) можно рассмотреть библиотеку resty:
import "github.com/go-resty/resty/v2"
client := resty.New()
resp, err := client.R().
SetHeader("Authorization", "Bearer my-token").
SetHeader("Accept", "application/json").
Get("https://api.example.com/data")
Этот подход удобен для быстрого прототипирования, но для production-кода лучше использовать нативный способ из первого ответа — он дает больше контроля и не добавляет зависимостей.
Ответов пока нет.
Войдите чтобы оставить ответ