Глава 1

HTTP-методы

Разберём из чего состоит HTTP-сообщение, зачем нужны методы и как они влияют на кеширование, ретраи и поведение веб-серверов.

📖 ~15 мин Основы

Что такое HTTP

HTTP (HyperText Transfer Protocol) — это протокол по которому браузер и сервер общаются друг с другом. Проще говоря — набор правил как задавать вопросы и давать ответы.

Ты вводишь адрес сайта в браузере → браузер отправляет запрос на сервер → сервер возвращает ответ → браузер показывает страницу. Всё что ты видишь в интернете работает именно так.

👤
Пользователь
вводит example.com
🌐
Браузер
формирует запрос
Запрос
«Дай мне страницу»
Ответ
«Вот HTML и стили»
🖥️
Веб-сервер
обрабатывает, отвечает
🖼️
Страница открылась
Браузер отрисовал полученный HTML — пользователь видит сайт

Каждый клик, каждая картинка, каждая кнопка — это отдельный запрос и ответ. HTTP просто описывает как именно они должны выглядеть чтобы обе стороны друг друга понимали.

Анатомия HTTP-сообщения

HTTP-сообщение — это просто текст. Никакой магии. Запрос и ответ имеют одинаковую структуру из трёх частей.

✉️
Аналогия: обычное письмо Стартовая строка — адрес на конверте. Заголовки — штампы и реквизиты. Тело — содержимое письма внутри.

Запрос (Request) — от клиента к серверу

POST /api/users HTTP/1.1 стартовая строка
Host: api.example.com заголовок
Content-Type: application/json заголовок
Authorization: Bearer eyJhb... заголовок
Content-Length: 47 заголовок
  пустая строка
{"name": "Алексей", "email": "alex@mail.ru"} тело

Ответ (Response) — от сервера к клиенту

HTTP/1.1 201 Created статусная строка
Content-Type: application/json заголовок
Location: /api/users/43 заголовок
  пустая строка
{"id": 43, "name": "Алексей"} тело

Три части подробно

Стартовая строка — всегда одна, всегда первая. В запросе: метод + путь + версия. В ответе: версия + код статуса + текст. Больше ничего.

Запрос
POST метод
 
/api/users путь
 
HTTP/1.1 версия
Ответ
HTTP/1.1 версия
 
201 код
 
Created текст

Заголовки (Headers) — главный инструмент управления HTTP. Формат жёсткий: Имя: Значение, по одному на строку. Заголовки — это инструкции, а не данные.

Content-Type
:
application/json
Говорит серверу: «тело — JSON, парси соответственно»
Authorization
:
Bearer eyJhb…
Токен доступа — кто делает запрос и что ему можно
Host
:
api.example.com
веб-сервер выбирает нужный виртуальный хост по этому полю
Content-Length
:
47
«Тело ровно 47 байт» — читать ровно столько

Пустая строка — обязательный разделитель. Сервер читает заголовки до пустой строки, затем переключается на чтение тела. Без неё протокол сломается.

Тело (Body) — собственно данные. У GET и DELETE тела обычно нет. У POST/PUT/PATCH — есть. Формат описывается заголовком Content-Type.

Анатомия URL

В стартовой строке запроса стоит путь — /api/users/42. Но клиент сначала разбирает полный URL чтобы понять куда подключаться и что запрашивать.

URL
https://api.example.com:8443/api/users/42?active=true&limit=10#section2
└──┬──┘  └──────┬────────┘└┬─┘└─────┬─────┘└──────────┬────────┘└───┬──┘
scheme       host        port     path             query        fragment
ЧастьЧто делаетПример
scheme Протокол — определяет как подключаться https → TLS + HTTP, http → без шифрования
host Доменное имя — определяет к какому серверу подключаться. Браузер резолвит его в IP через DNS api.example.com
port Порт на сервере. Если не указан — используется порт по умолчанию: 443 для HTTPS, 80 для HTTP :8443
path Путь к ресурсу — именно он попадает в стартовую строку запроса /api/users/42
query Параметры после ?, разделённые &. Пары ключ=значение для фильтрации, пагинации, поиска ?active=true&limit=10
fragment Якорь после #. Указывает на конкретное место на странице #section2

Из всего URL в HTTP-запрос попадают только path + query:

HTTP Request
GET /api/users/42?active=true&limit=10 HTTP/1.1
Host: api.example.com
ℹ️
Что куда уходит Scheme нужна браузеру чтобы выбрать протокол. Host уходит в заголовок Host. Port нужен для TCP-соединения. Fragment вообще не уходит на сервер — браузер использует его локально для прокрутки страницы.

Что такое HTTP-метод

HTTP — протокол прикладного уровня поверх TCP. Когда браузер обращается к серверу, первое что он указывает — метод (иногда его называют verb, глагол). Метод говорит серверу: что именно ты хочешь сделать с ресурсом.

HTTP Request
GET /api/users/42 HTTP/1.1
Host: api.example.com
Accept: application/json
Authorization: Bearer eyJhbGci...

Первая строка — стартовая: <МЕТОД> <путь> <версия>. Всё остальное — заголовки. Тело (если есть) идёт после пустой строки.

Два ключевых свойства методов

Безопасность (Safe)

Безопасный метод не изменяет состояние сервера — только читает данные. Можно вызывать сколько угодно раз без побочных эффектов.

⚠️
«Безопасный» ≠ «зашифрованный» Это исключительно про изменение данных на сервере, не про шифрование соединения.

Идемпотентность (Idempotent)

Идемпотентный метод при повторном вызове с теми же параметрами даёт тот же результат. Это важно для ретраев: если соединение оборвалось — можно безопасно повторить запрос.

Метод Безопасный Идемпотентный
GET ✓ да ✓ да
HEAD ✓ да ✓ да
OPTIONS ✓ да ✓ да
POST ✗ нет ✗ нет
PUT ✗ нет ✓ да
PATCH ✗ нет ~ нет*
DELETE ✗ нет ✓ да

* PATCH может быть идемпотентным если реализован корректно, но по спецификации — гарантии нет.

Вложенность: безопасность ⊂ идемпотентность

Все три безопасных метода одновременно идемпотентны. Это не случайность — если метод не меняет состояние вообще, то повторный вызов по определению даст тот же результат. Безопасность автоматически влечёт идемпотентность.

Обратное неверно: DELETE удаляет ресурс (изменение!), но второй DELETE уже ничего не меняет — ресурса нет. Безопасным не является, а идемпотентным — да.

Вложенные множества методов
Все методы ИДЕМПОТЕНТНЫЕ БЕЗОПАСНЫЕ GET HEAD OPTIONS PUT DELETE POST PATCH
💡
Безопасность — более строгое условие чем идемпотентность. Каждый безопасный метод идемпотентен, но не каждый идемпотентный метод безопасен.

Методы по одному

GET
Получить данные
безопасный идемпотентный
POST
Создать ресурс
не безопасный не идемпотентный
PUT
Заменить целиком
не безопасный идемпотентный
PATCH
Частичное обновление
не безопасный условно
DELETE
Удалить ресурс
не безопасный идемпотентный
HEAD
Только заголовки
безопасный идемпотентный
OPTIONS
Что умеет сервер
безопасный идемпотентный

GET — получить данные

Самый используемый метод. Не имеет тела. Параметры передаются в URL через query string.

Request
GET /api/users?page=2&limit=20 HTTP/1.1
Host: api.example.com
Response
HTTP/1.1 200 OK
Content-Type: application/json

[
  { "id": 21, "name": "Алексей" },
  { "id": 22, "name": "Мария" }
]

Типичные коды: 200 OK · 404 Not Found · 304 Not Modified

HTTP-песочница ИНТЕРАКТИВ
РЕСУРСЫ
👤 Users 3
📄 Posts 3
📦 Products 5
ПОДСКАЗКИ

Введи HTTP-запрос в текстовое поле.

Формат:
МЕТОД /путь HTTP/1.1

ЗАПРОС
ОТВЕТ
Raw Заголовки Тело
Ответ появится здесь...
БАЗА ДАННЫХ СЕРВЕРА
Users Posts Products

POST — создать ресурс

Создаёт новый ресурс. Данные — в теле. Не идемпотентный: два одинаковых POST создадут две записи.

Request
POST /api/users HTTP/1.1
Host: api.example.com
Content-Type: application/json

{
  "name": "Новый пользователь",
  "email": "user@example.com"
}
Response
HTTP/1.1 201 Created
Location: /api/users/43
Content-Type: application/json

{ "id": 43, "name": "Новый пользователь", "email": "user@example.com" }
HTTP-песочница — POST ИНТЕРАКТИВ
РЕСУРСЫ
👤 Users 2
ПОДСКАЗКИ

Введи HTTP-запрос в текстовое поле.

Формат:
МЕТОД /путь HTTP/1.1

⚠ Лимит: не более 5 записей в базе

ЗАПРОС
ОТВЕТ
Raw Заголовки Тело
Ответ появится здесь...
БАЗА ДАННЫХ СЕРВЕРА

PUT — полностью заменить ресурс

Заменяет ресурс целиком. Передаёшь полное новое представление — сервер заменяет старое на новое. Идемпотентный.

⚠️
Ключевое отличие от PATCH Если в теле PUT не указать поле email — оно будет удалено или сброшено в null. PUT заменяет весь объект.
Request
PUT /api/users/43 HTTP/1.1
Content-Type: application/json

{
  "name": "Изменённое имя",
  "email": "changed@example.com"
}
HTTP-песочница — PUT ИНТЕРАКТИВ
РЕСУРСЫ
ПОДСКАЗКИ

Замени весь объект целиком.

Формат:
МЕТОД /путь/id HTTP/1.1

⚠ Не указал поле — оно станет null

ЗАПРОС
ОТВЕТ
Raw Заголовки Тело
Ответ появится здесь...
БАЗА ДАННЫХ СЕРВЕРА

PATCH — частично обновить ресурс

Обновляет только указанные поля. Не нужно передавать весь объект.

Request
PATCH /api/users/43 HTTP/1.1
Content-Type: application/json

{ "email": "only_email_changed@example.com" }
HTTP-песочница — PATCH ИНТЕРАКТИВ
РЕСУРСЫ
ПОДСКАЗКИ

Обнови только нужные поля.

Формат:
МЕТОД /путь/id HTTP/1.1

✓ Не указал поле — оно сохранится

ЗАПРОС
ОТВЕТ
Raw Заголовки Тело
Ответ появится здесь...
БАЗА ДАННЫХ СЕРВЕРА

DELETE — удалить ресурс

Удаляет ресурс. Идемпотентный: повторный DELETE вернёт 404, но состояние сервера одинаковое — ресурса нет.

Request → Response
DELETE /api/users/43 HTTP/1.1

HTTP/1.1 204 No Content
HTTP-песочница — DELETE ИНТЕРАКТИВ
РЕСУРСЫ
ПОДСКАЗКИ

Удали ресурс по ID.

Формат:
МЕТОД /путь/id HTTP/1.1

Повторный DELETE → 404 (идемпотентность)

ЗАПРОС
ОТВЕТ
Raw Заголовки Тело
Ответ появится здесь...
БАЗА ДАННЫХ СЕРВЕРА

HEAD — только заголовки, без тела

Как GET, но сервер возвращает только заголовки — без тела. Используется чтобы проверить существование ресурса или узнать метаданные без скачивания.

📋
Типичный сценарий Проверить размер файла перед скачиванием, проверить валидность URL, мониторинг аптайма.

OPTIONS — что умеет сервер

Запрашивает список поддерживаемых методов. Ключевой элемент механизма CORS preflight.

CORS Preflight
OPTIONS /api/users HTTP/1.1
Origin: https://frontend.example.com
Access-Control-Request-Method: DELETE

HTTP/1.1 200 OK
Allow: GET, POST, PUT, PATCH, DELETE, OPTIONS
Access-Control-Allow-Origin: https://frontend.example.com
Access-Control-Allow-Methods: GET, POST, DELETE

Коды ответа

Коды делятся на пять классов по первой цифре.

ДиапазонКлассСмысл
1xxInformationalПромежуточный ответ (редко встречается)
2xxSuccessЗапрос выполнен успешно
3xxRedirectionКлиент должен сделать ещё один запрос
4xxClient ErrorОшибка на стороне клиента
5xxServer ErrorОшибка на стороне сервера

2xx — успех

200
OK
Стандартный успех
201
Created
Ресурс создан (POST). Возвращай Location с URL нового ресурса
204
No Content
Успех, тела нет (DELETE, PUT)
206
Partial Content
Частичный контент (range-запросы, видео)

3xx — перенаправление

301
Moved Permanently
Постоянный редирект — кешируется браузером
302
Found
Временный редирект — не кешируется
304
Not Modified
Ресурс не изменился, используй кеш
307
Temporary Redirect
Временный, но метод сохраняется (POST остаётся POST)
308
Permanent Redirect
Постоянный, метод сохраняется

4xx — ошибка клиента

400
Bad Request
Невалидный запрос: неправильный JSON, отсутствует поле
401
Unauthorized
Не аутентифицирован (нет токена)
403
Forbidden
Аутентифицирован, но нет прав
404
Not Found
Ресурс не найден
405
Method Not Allowed
Метод не поддерживается этим эндпоинтом
409
Conflict
Конфликт (например, email уже занят)
422
Unprocessable Entity
Данные пришли корректно, но не прошли валидацию
429
Too Many Requests
Превышен rate limit

5xx — ошибка сервера

500
Internal Server Error
Что-то сломалось на бэкенде
502
Bad Gateway
nginx не смог получить ответ от бэкенда (упал или вернул мусор)
503
Service Unavailable
Сервис временно недоступен (перегрузка, деплой)
504
Gateway Timeout
Бэкенд не ответил вовремя (превышен proxy_read_timeout)

Итог

HTTP-методы — это соглашение. Технически никто не мешает делать DELETE через POST. Но соблюдение семантики даёт три преимущества:

🗄️
Кеширование
GET и HEAD можно кешировать, остальные методы нельзя. Браузер кешируют GET когда сервер разрешает.
🔄
Ретраи
Безопасны для идемпотентных методов без риска дублей
📖
Читаемость
Любой разработчик или администратор глядя на запрос сразу понимает что он делает, без документации.