Урок 6 — HTTP: язык интернета

HTTP — это «язык», на котором браузер разговаривает с веб-сервером. На нём же работают API, мобильные приложения, микросервисы. Понять его — значит понять 80% того, что происходит в вашем продакшене.

В этом уроке
  1. Что такое HTTP
  2. URL — анатомия адреса
  3. Что такое запрос
  4. Методы HTTP
  5. Что такое ответ
  6. Коды статуса
  7. Заголовки
  8. Куки и сессии
  9. HTTP/1.1 vs HTTP/2 vs HTTP/3
  10. REST — стиль построения API
  11. Что с этим делает DevOps
  12. Команды и упражнения
  13. Чек-лист
  14. Задачи с ответами
Вспомни из прошлых уроков

DNS превратил имя в IP (урок 5), TCP установил надёжное соединение с портом 80/443 сервера (урок 4). Труба готова — теперь по ней потечёт «разговор». HTTP — это язык этого разговора, причём текстовый: его можно читать глазами и писать руками. Именно поэтому дебаг веба доступен любому, кто дочитает этот урок.

1. Что такое HTTP

HTTP — HyperText Transfer Protocol. Изначально создан для передачи HTML-страниц («гипертекста»), но сейчас на нём работают: страницы, API, файлы, видео, чаты, всё что угодно.

Принципы:

HTTP работает поверх TCP (а HTTPS — поверх TCP+TLS). По умолчанию HTTP использует порт 80, HTTPS — 443.

2. URL — анатомия адреса

То, что ты вводишь в адресной строке, называется URL (Uniform Resource Locator). У него строго определённая структура:

Структура URL https://api.example.com:443/users/42?tab=info#section-2 схема хост (домен) порт (опц.) путь query fragment https — какой протокол использовать (http / https / ftp / ssh / file) :443 — порт. Если 80 для http или 443 для https — можно опустить ?tab=info — параметры. Несколько пишут через &: ?a=1&b=2

На сервер ушло всё, кроме fragment (всё, что после #) — это обрабатывается только в браузере и сервер о нём не знает.

3. Что такое запрос

HTTP-запрос — это просто текст. Вот как он выглядит «изнутри», без браузерной обёртки:

GET /users/42 HTTP/1.1
Host: api.example.com
User-Agent: Mozilla/5.0
Accept: application/json
Authorization: Bearer eyJhbGc...
Cookie: session=abc123

(пустая строка — конец заголовков)
(тело запроса — для GET обычно пустое)

Структура — три части:

  1. Стартовая строка: метод + путь + версия HTTP
  2. Заголовки: мета-информация, ключ-значение
  3. Тело (body): данные (для POST, PUT, PATCH). Пустое для GET

4. Методы HTTP

Метод говорит серверу, что мы хотим сделать с ресурсом. Их немного, и каждый имеет свой смысл:

МетодЧто делаетИдемпотентен?
GETПолучить ресурс. Не меняет состояние сервера✓ Да
POSTСоздать ресурс / отправить данные✗ Нет (повторный запрос создаст ещё один)
PUTПолностью заменить ресурс✓ Да
PATCHЧастично обновить ресурс✗ Обычно нет
DELETEУдалить ресурс✓ Да (удалить дважды — то же самое)
HEADКак GET, но без тела ответа — только заголовки✓ Да
OPTIONSУзнать, какие методы поддерживает сервер (используется в CORS)✓ Да
Идемпотентность

«Идемпотентный» — значит «повторение даёт тот же результат». Сделал GET 5 раз — ничего не сломал. Сделал POST 5 раз — у тебя 5 одинаковых записей. Это важно: retry в инфраструктуре безопасны только для идемпотентных запросов.

5. Что такое ответ

HTTP/1.1 200 OK
Date: Wed, 15 May 2026 12:00:00 GMT
Content-Type: application/json; charset=utf-8
Content-Length: 87
Cache-Control: max-age=300
Server: nginx/1.25.0

{"id": 42, "name": "Alice", "email": "alice@example.com"}

Структура та же — стартовая строка (теперь с кодом статуса), заголовки, тело.

6. Коды статуса

Трёхзначное число, которое говорит результат запроса. Группируется по первой цифре:

1xx — Информационные

Редко встречаются в обычной жизни. 101 Switching Protocols — переход на WebSocket.

2xx — Успех

  • 200 OK — всё хорошо, держи ответ
  • 201 Created — ресурс создан (часто после POST)
  • 204 No Content — успех, но тела нет

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

  • 301 Moved Permanently — навсегда переехал
  • 302 Found — временно переехал
  • 304 Not Modified — у тебя уже есть свежая версия в кэше

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

  • 400 Bad Request — ты прислал ерунду
  • 401 Unauthorized — кто ты вообще такой?
  • 403 Forbidden — кто ты — знаю, но тебе нельзя
  • 404 Not Found — такого нет
  • 409 Conflict — конфликт состояний (например, уже существует)
  • 429 Too Many Requests — rate limit, притормози

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

  • 500 Internal Server Error — у сервера что-то упало
  • 502 Bad Gateway — LB получил от backend мусор / backend упал
  • 503 Service Unavailable — нет здоровых backend-ов / перегрузка
  • 504 Gateway Timeout — backend не ответил вовремя
DevOps-интерпретация 5xx

502 / 503 / 504 — отдельно учиться различать:

7. Заголовки

Заголовки — это пары «ключ: значение», которые несут метаданные. Их сотни, но десятка нужно знать наизусть:

ЗаголовокКто шлётЗачем
HostКлиентКакой домен открываем (на одном IP может быть много сайтов)
User-AgentКлиентКакой браузер / клиент
AcceptКлиентВ каком формате хотим ответ (HTML, JSON, XML)
AuthorizationКлиентУчётка / токен. Обычно Bearer <jwt>
CookieКлиентСохранённые сервером значения (сессия и т.п.)
Content-TypeОбаВ каком формате тело: application/json, text/html
Content-LengthОбаСколько байт в теле
Cache-ControlСерверКак клиенту кэшировать ответ
Set-CookieСервер«Установи у себя такую куку»
LocationСерверКуда редиректить (при 3xx)
X-Forwarded-ForПрокси/LBРеальный IP клиента (когда позади LB)
Strict-Transport-SecurityСервер«Всегда заходи по HTTPS» (HSTS, security-заголовок)

8. Куки и сессии

HTTP без состояния. Сервер сам по себе не знает, что ты тот же пользователь, который заходил минуту назад. Чтобы запомнить — придумали куки (cookies).

Механика:

  1. Клиент логинится — отправляет username/password
  2. Сервер проверяет, создаёт сессию, шлёт ответ с Set-Cookie: session=abc123
  3. Браузер запоминает эту куку
  4. В каждом следующем запросе клиент шлёт Cookie: session=abc123
  5. Сервер видит куку, находит сессию, понимает «это Alice»

У кук есть важные атрибуты безопасности:

В современных приложениях вместо «классических сессий с кукой» часто используют JWT-токены в заголовке Authorization. Принцип тот же — клиент несёт удостоверение в каждом запросе.

9. HTTP/1.1 vs HTTP/2 vs HTTP/3

HTTP/1.1 (1997)HTTP/2 (2015)HTTP/3 (2022)
ФорматТекстБинарныйБинарный
ТранспортTCPTCPQUIC поверх UDP
MultiplexingНет (один запрос — одно соединение)Да, параллельно в одном TCPДа, без head-of-line blocking
Сжатие заголовковНетHPACKQPACK
Push от сервераНетДа (редко используется)Нет (убрали как ненужное)

На практике: современный продакшен — HTTP/2 везде (TLS требует HTTP/2 в новых браузерах). HTTP/3 — растущий стандарт; Cloudflare, Google, Meta уже массово на нём. Учи как «знать о существовании», но HTTP/2 пока главный.

10. REST — стиль API

REST (Representational State Transfer) — это не протокол, а стиль построения HTTP-API. Идея:

# Получить список пользователей
GET    /users

# Получить одного
GET    /users/42

# Создать нового
POST   /users        + body { "name": "Bob" }

# Обновить
PATCH  /users/42     + body { "name": "Alice" }

# Удалить
DELETE /users/42

Альтернативы REST — GraphQL (один POST-эндпоинт, гибкая query), gRPC (бинарный, поверх HTTP/2, для микросервисов). Знай о существовании.

11. Что с этим делает DevOps

12. Команды и упражнения

curl — лучший друг

# Простой GET
curl https://api.example.com/users/42

# Подробный вывод (с заголовками запроса и ответа)
curl -v https://api.example.com/users/42

# Только заголовки ответа (HEAD)
curl -I https://api.example.com/

# POST с JSON
curl -X POST \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer eyJhbGc..." \
  -d '{"name": "Alice"}' \
  https://api.example.com/users

# Следовать редиректам
curl -L https://example.com

# Сохранить ответ в файл
curl -o page.html https://example.com

# Тайминги — где медленно
curl -w "DNS: %{time_namelookup}s | Connect: %{time_connect}s | TLS: %{time_appconnect}s | Total: %{time_total}s\n" \
     -o /dev/null -s https://example.com

HTTPie — дружелюбная альтернатива

# Подсветка JSON, удобный синтаксис
sudo apt install httpie
http GET https://api.example.com/users/42
http POST https://api.example.com/users name=Alice email=alice@example.com

Сделать HTTP-запрос «руками»

nc example.com 80
GET / HTTP/1.1
Host: example.com
Connection: close

# (двойной Enter)
# Сервер ответит сырым HTTP — увидишь заголовки + тело

13. Чек-лист «понимаю это»

14. Задачи — реши сам (ответы спрятаны)

Задача 1. Разбери URL по частям: https://api.shop.example.com:8443/v2/orders?status=paid&limit=10#top

Схема — https; хост — api.shop.example.com (поддомен api у shop.example.com); порт — 8443 (нестандартный, поэтому указан явно); путь — /v2/orders; query-параметры — status=paid и limit=10; фрагмент — #top (на сервер вообще не отправляется — живёт только в браузере!).

Задача 2. Пользователь дважды случайно нажал «Обновить» на странице заказа — и заказ создался дважды. Какой метод использовали разработчики неправильно и почему?

Создание заказа повесили на GET (или повторили POST без защиты). GET обязан быть безопасным и идемпотентным — только читать, ничего не менять: браузеры свободно повторяют GET при обновлении. Изменяющие действия — POST/PUT/DELETE, плюс защита от повторной отправки. Это не педантизм — это реальные дважды списанные деньги.

Задача 3. Чем 401 отличается от 403? Придумай по житейскому примеру на каждый.

401 Unauthorized — «я не знаю, кто ты»: нет/просрочен токен или логин. Пример: пытаешься войти в подъезд без ключа. 403 Forbidden — «я знаю, кто ты, но тебе нельзя»: аутентифицирован, но нет прав. Пример: ключ от подъезда есть, но квартира соседа заперта для тебя. В дебаге: 401 → чини аутентификацию, 403 → чини права/роли.

Задача 4. Мониторинг показывает всплеск 502 от твоего Nginx. Что это значит и где искать проблему — в Nginx или за ним?

502 Bad Gateway = Nginx (прокси) жив и отвечает, но приложение за ним вернуло мусор или не отвечает вовсе (упало, перезапускается, не слушает порт). Искать за прокси: живо ли приложение, слушает ли свой порт (плейбук урока 4). Сравни: 503 — «перегружен/недоступен временно», 504 — «бэкенд слишком долго думал» (таймаут).

Задача 5. Ты залогинился на сайте, закрыл вкладку, открыл снова — и всё ещё залогинен. Как это работает, если HTTP «без памяти»?

При логине сервер выдал cookie (заголовок Set-Cookie), браузер сохранил её и теперь автоматически прикладывает к каждому запросу на этот домен (заголовок Cookie). Сервер по ней узнаёт твою сессию. Сам HTTP остался stateless — «память» живёт в паре cookie ↔ сессия на сервере.

Задача 6. REST-вопрос: спроектируй методы и пути для операций над товарами интернет-магазина: список, один товар, создать, изменить цену, удалить.

GET /products — список; GET /products/42 — один; POST /products — создать (тело с данными); PATCH /products/42 — частично изменить (цену); DELETE /products/42 — удалить. Существительные во множественном числе в пути, действие выражается методом — это и есть REST-стиль.

HTTP — текстовый протокол «запрос-ответ» поверх TCP. URL содержит схему/хост/порт/путь/query. Методы: GET, POST, PUT, PATCH, DELETE. Статусы: 2xx ок, 3xx редирект, 4xx ошибка клиента, 5xx ошибка сервера. Заголовки несут метаданные. HTTP/2 — стандарт сегодня, HTTP/3 на подходе. REST = HTTP-стиль для API.
Мост к следующему уроку

Один тревожный факт: всё, что ты писал в этом уроке через curl http://…, летело по сети открытым текстом — любой узел по пути (Wi-Fi кафе, провайдер, роутер) мог прочитать твои заголовки, куки и пароли. Как интернет решил эту проблему — и что на самом деле значит «замочек» в браузере — в следующем уроке про HTTPS и TLS. Это самая красивая инженерная история всего пути.

← Назад
Урок 5: DNS