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

Из чего состоит http запрос

1.7 Middle🔥 231 комментариев
#Сетевые протоколы и API

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

🐱
deepseek-v3.2PrepBro AI5 апр. 2026 г.(ред.)

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

Структура HTTP-запроса

HTTP-запрос (HyperText Transfer Protocol) — это структурированное сообщение, которое клиент (например, браузер или ваш Go-приложение) отправляет серверу для получения или изменения ресурса. В Go, при разработке веб-сервисов, мы напрямую работаем с этими компонентами через пакет net/http. Давайте разберем состав запроса подробно.

Основные компоненты HTTP-запроса

1. Стартовая строка (Request Line)

Это первая строка запроса, которая определяет базовое действие. Формат: Метод URI Версия_протокола.

  • Метод (HTTP Method): Определяет операцию над ресурсом. Основные методы:
    *   `GET` — получение ресурса.
    *   `POST` — создание ресурса или отправка данных.
    *   `PUT` — полное обновление ресурса.
    *   `DELETE` — удаление ресурса.
    *   `PATCH`, `HEAD`, `OPTIONS` и другие.
  • URI (Uniform Resource Identifier): Путь к целевому ресурсу на сервере (например, /api/users или /index.html). Может включать строку запроса (query string).
  • Версия протокола: Указывает версию HTTP (например, HTTP/1.1 или HTTP/2).

В Go эту информацию можно извлечь из объекта *http.Request:

req.Method  // GET, POST, etc.
req.URL.Path // /api/users
req.Proto   // HTTP/1.1

2. Заголовки (Headers)

Это набор пар ключ-значение, которые передают метаинформацию о запросе, клиенте, теле запроса и параметрах кэширования. Заголовки отделяются от стартовой строки и тела пустой строкой.

  • Общие заголовки: Date, Cache-Control, Connection.
  • Заголовки запроса: User-Agent, Accept (типы контента, которые понимает клиент), Authorization (данные для аутентификации).
  • Заголовки сущности (тела): Content-Type (тип данных тела, например, application/json), Content-Length.

В Go работа с заголовками осуществляется через map Header:

// Чтение заголовка
contentType := req.Header.Get("Content-Type")
authHeader := req.Header.Get("Authorization")

// Установка заголовков в клиентском запросе
req, _ := http.NewRequest("GET", url, nil)
req.Header.Set("User-Agent", "MyGoApp/1.0")
req.Header.Add("Accept", "application/json")

3. Тело запроса (Body)

Необязательная часть, которая содержит данные, отправляемые на сервер. Используется в методах POST, PUT, PATCH. Тело может быть в различных форматах: JSON, XML, форма (application/x-www-form-urlencoded), бинарные данные (загрузка файлов).

Важно: Для чтения тела в Go, Body является io.ReadCloser. Его можно прочитать только один раз. Часто используют готовые методы, такие как ioutil.ReadAll (устарел) или io.ReadAll в Go 1.16+.

// Чтение тела запроса как JSON
type User struct {
    Name string `json:"name"`
    Age  int    `json:"age"`
}
var u User
body, _ := io.ReadAll(req.Body)
json.Unmarshal(body, &u)

// Или с помощью готового декодера (предпочтительно)
err := json.NewDecoder(req.Body).Decode(&u)

Пример полного HTTP-запроса

POST /api/login HTTP/1.1
Host: example.com
User-Agent: Mozilla/5.0
Content-Type: application/json
Authorization: Bearer eyJhbGciOiJIUzI1NiIs...
Content-Length: 56

{"username": "ivan", "password": "secret123"}

Особенности работы с запросами в Go

  1. Обработка форм: Для данных из HTML-форм (application/x-www-form-urlencoded или multipart/form-data) используйте методы req.ParseForm() и req.FormValue("key").

    req.ParseForm()
    username := req.FormValue("username")
    // Или для многозначных полей (например, чекбоксы)
    interests := req.Form["interest"]
    
  2. Параметры строки запроса (Query Parameters): Доступны через req.URL.Query().

    query := req.URL.Query()
    page := query.Get("page") // Получает первое значение
    filters := query["filter"] // Получает срез всех значений для ключа "filter"
    
  3. Контекст запроса: Объект *http.Request в Go содержит Context, который используется для передачи данных, управления таймаутами и отмены операций в рамках цепочки вызовов, связанных с этим запросом.

    ctx := req.Context()
    // Установка контекста с таймаутом для дочерних операций (например, запрос к БД)
    newCtx, cancel := context.WithTimeout(ctx, 2*time.Second)
    defer cancel()
    
  4. Мультипарт-запросы (загрузка файлов): Для обработки файлов используется req.ParseMultipartForm() и req.MultipartForm.File.

    err := req.ParseMultipartForm(10 << 20) // Макс. 10 МБ
    file, header, err := req.FormFile("uploaded_file")
    defer file.Close()
    

Понимание деталей HTTP-запроса критически важно для разработки надежных, безопасных и эффективных веб-сервисов на Go. Пакет net/http предоставляет удобные абстракции, но знание "низкоуровневого" устройства запроса позволяет глубже отлаживать проблемы, правильно проектировать API и оптимизировать взаимодействие между клиентом и сервером.