HTTP и HTTPS
Request/response, методы, статусы, заголовки. HTTP/1.1 vs 2 в двух абзацах.
Модель request/response
HTTP устроен как разговор по очереди: клиент спросил, сервер ответил. В HTTP/1.1 в одном соединении нет одновременных потоков и сервер не отвечает по своей инициативе (в HTTP/2 запросы мультиплексируются, см. ниже).
Запрос:
POST /api/login HTTP/1.1
Host: example.com
Content-Type: application/json
Authorization: Bearer eyJhbG...
Content-Length: 42
{"email":"a@b.com","password":"secret"}
Ответ:
HTTP/1.1 200 OK
Content-Type: application/json
Set-Cookie: session=abc123; HttpOnly; Secure
Content-Length: 27
{"token":"eyJhbGciOiJI..."}
Структура одинаковая: первая строка (метод+путь или статус), затем заголовки, пустая строка, тело.
Но до того, как клиент сможет отправить этот запрос, TCP должен открыть соединение — три пакета между клиентом и сервером:
Дальше, если это HTTPS, сразу после TCP идёт TLS-handshake, и только потом клиент отправляет HTTP-запрос и получает ответ. Эти три пакета SYN/SYN-ACK/ACK — «себестоимость» любого TCP-соединения, ~1 RTT накладных.
Методы
| Метод | Что делает | Идемпотентный | С телом |
|---|---|---|---|
GET | прочитать ресурс | да | не принято¹ |
POST | создать / любое действие | нет | да |
PUT | заменить ресурс целиком | да | да |
PATCH | частично обновить | нет² | да |
DELETE | удалить | да | редко |
HEAD | как GET, но без тела (только headers) | да | нет |
OPTIONS | какие методы доступны (используется CORS) | да | нет |
Идемпотентность — «повторный вызов даёт тот же результат». Это
важно для retry-логики: GET и PUT можно безопасно повторять,
POST — нет (можно случайно создать два заказа).
¹ Тело у GET стандарт не запрещает (RFC 9110), но серверы и прокси его
обычно игнорируют, поэтому так не делают.
² PATCH не идемпотентен по определению (RFC 5789), но конкретный патч
можно спроектировать идемпотентным (например, «установить поле в X»).
Статусы
Первая цифра задаёт класс:
- 1xx — информационные, редко встречаются (
100 Continue). - 2xx — успех.
- 3xx — редирект.
- 4xx — ошибка клиента (он что-то не так послал).
- 5xx — ошибка сервера (он не справился).
Самые ходовые наизусть:
| Код | Когда |
|---|---|
200 OK | стандартный успех |
201 Created | создан новый ресурс (после POST) |
204 No Content | успех, тела ответа нет (после DELETE) |
301 Moved Permanently | редирект навсегда (кешируется) |
302 Found | редирект временный |
304 Not Modified | у тебя свежая копия, отдавать заново нечего |
400 Bad Request | запрос невалиден, исправь |
401 Unauthorized | не аутентифицирован, залогинься |
403 Forbidden | аутентифицирован, но прав нет |
404 Not Found | ресурс не существует |
409 Conflict | конфликт состояния (имя занято, версия устарела) |
422 Unprocessable Entity | синтаксически ок, семантически нет |
429 Too Many Requests | клиент превысил лимит запросов в секунду/минуту, нужно подождать (часто в заголовке Retry-After указано сколько) |
500 Internal Server Error | сервер упал |
502 Bad Gateway | прокси не дозвонился до апстрима |
503 Service Unavailable | сервис временно недоступен |
504 Gateway Timeout | прокси дозвонился, но апстрим не успел ответить |
502/503/504 — три ошибки, которые DevOps видит чаще всего. Учись
различать:
502— прокси (nginx/Caddy) не может установить соединение с backend'ом (упал, не слушает порт),503— сам сервис говорит "я не могу обслужить" (перегрузка, плановое отключение),504— соединение есть, но backend не уложился в таймаут.
Заголовки, которые встретишь
| Заголовок | Зачем |
|---|---|
Content-Type | какой формат у тела: application/json, text/html |
Content-Length | размер тела в байтах |
Authorization | токен / basic-auth / Bearer |
Cookie / Set-Cookie | сессия и состояние |
User-Agent | кто клиент (браузер, бот, curl) |
Cache-Control | как клиенту/прокси кешировать |
ETag / If-None-Match | условный запрос: верни только если изменилось |
Host | какой домен запрашивается (важно при multi-tenant nginx) |
X-Forwarded-For | оригинальный IP клиента, когда есть прокси |
HTTPS
HTTPS — это HTTP, обёрнутый в TLS. Что добавляется:
- порт 443 вместо 80,
- шифрование трафика — провайдер видит только домен (по SNI), но не путь/параметры/тело,
- сертификат — подтверждение, что ты говоришь с настоящим
example.com, а не с MITM.
Сертификаты сегодня бесплатные (Let's Encrypt), сайт на обычном HTTP без TLS в проде — редкий артефакт. Caddy и Traefik выпускают и обновляют сертификат автоматически — тебе достаточно указать домен.
Подробности TLS (handshake, версии 1.2 vs 1.3, как именно работает шифрование) — это отдельная большая тема, к HTTP она прилипает только снаружи. На уровне приложения с HTTPS работаешь как с обычным HTTP.
HTTP/1.1 vs 2 vs 3
HTTP/1.1 — текстовый, одно TCP-соединение = одна запрос/ответ за раз. Чтобы открыть страницу с 50 ресурсами, браузер открывает 6 параллельных коннектов и плачет.
HTTP/2 — бинарный, мультиплекс в одном TCP: десятки запросов
одновременно. Headers сжимаются (HPACK). Сервер-push был, но Chrome
выключил его поддержку в 2022. Похожую задачу частично решает 103 Early Hints (отдельная фича, не прямая замена): сервер успевает подсказать
клиенту, какие ресурсы скоро понадобятся, ещё до основного ответа.
HTTP/3 — построен поверх QUIC (это уже UDP, не TCP). Решает проблему head-of-line blocking при потере пакетов. Заметно лучше на мобильных и нестабильных сетях. Поддержка в браузерах и серверах есть, но не везде в инфраструктуре.
Тебе как DevOps интересно: nginx, Caddy, ALB — все умеют h2 и h3 (h3 -
не всегда), включается обычно одной опцией. Видеть это можно в
curl -v --http2 и curl --http3.
CORS — почему «работает локально, не работает в браузере»
CORS (Cross-Origin Resource Sharing) — механизм браузера, который
запрещает страницам с одного origin (например https://app.example.com)
дёргать API на другом origin (https://api.example.com), если сервер
явно не разрешил.
Как это выглядит у юзера: фронт делает fetch("https://api.example.com/me"),
в браузере красная ошибка про CORS, в консоли что-то типа
«No 'Access-Control-Allow-Origin' header». А curl https://api.example.com/me
из терминала работает — CORS это правило браузера, не сервера.
Как сервер разрешает:
- На «простой» запрос просто отдаёт заголовок
Access-Control-Allow-Origin: https://app.example.com. Простой — этоGET/HEAD/POSTсContent-Typeтолькоapplication/x-www-form-urlencoded,multipart/form-dataилиtext/plainи без кастомных заголовков. - На «не-простой» (
POSTс JSON, custom headers, методы кроме GET/POST) браузер сначала шлёт preflightOPTIONS-запрос. Сервер должен ответить наборомAccess-Control-Allow-*заголовков: какой origin можно, какие методы, какие заголовки, нужны ли cookies (Allow-Credentials).
Типовые ошибки на проде:
- Поставили
Access-Control-Allow-Origin: *и забылиAllow-Credentials- кукины не летят, юзер не залогинен.
- На preflight забыли разрешить нужный заголовок (
Authorization,Content-Type: application/json) — запрос блокируется. - nginx отдаёт
Access-Control-*только на 2xx, а не на 4xx — юзер видит CORS-ошибку вместо реальной 401.
curl как способ всё посмотреть глазами
curl -v https://example.com # все заголовки + handshake + ответ
curl -I https://example.com # только response headers (HEAD)
curl -H "Authorization: Bearer X" ... # добавить заголовок
curl -X POST -d '{"a":1}' \
-H "Content-Type: application/json" \
https://api.example.com/x
curl --json '{"a":1}' https://api.example.com/x # curl 7.82+, короче
curl -L https://example.com # следовать редиректам
curl -o file.zip https://... # сохранить тело в файл
curl --resolve host:443:1.2.3.4 https://host/ # подменить DNS-резолв
curl -v показывает весь handshake, сертификат, заголовки в обе
стороны. Так выглядит вывод (строки * — это диагностика curl, > —
запрос, < — ответ):
$ curl -v https://example.com
* Trying 93.184.216.34:443...
* TLSv1.3 (OUT), TLS handshake, Client hello
* SSL connection using TLSv1.3 / TLS_AES_256_GCM_SHA384
> GET / HTTP/2
> Host: example.com
> user-agent: curl/8.5.0
< HTTP/2 200
< content-type: text/html; charset=UTF-8
< content-length: 1256
Видно цепочку: TCP-соединение, TLS-handshake с версией и шифром, потом сам HTTP-запрос и ответ. Это базовый инструмент диагностики HTTP-проблем.
На собесе спросят
Короткие ответы, которые надо уметь проговорить:
- «Чем 401 отличается от 403?» 401 — «кто ты?», не аутентифицирован, иди залогинься. 403 — «ты есть, но тебе сюда нельзя», прав не хватает.
- «Чем 502 отличается от 504?» 502 — прокси не дозвонился до бэкенда (упал, не слушает порт). 504 — дозвонился, но бэкенд не успел ответить в таймаут.
- «Что такое идемпотентный метод?» Повторный вызов даёт тот же
результат и состояние сервера не меняет дополнительно.
GET,PUT,DELETEидемпотентны,POSTиPATCHпо умолчанию нет (хотя конкретныйPATCHможно спроектировать идемпотентным). ПоэтомуPOSTнельзя безопасно retry-ить. - «Чем HTTP/2 отличается от HTTP/1.1?» В одном TCP-соединении одновременно идут несколько запросов и ответов (мультиплекс), не ждут друг друга. Заголовки сжимаются (HPACK), протокол бинарный, а не текстовый. Браузеру не нужно открывать 6 параллельных коннектов.
- «Что такое CORS и зачем preflight?» Защита браузера: страница с
одного origin не может дёргать API на другом origin без разрешения
сервера. На сложные запросы браузер шлёт
OPTIONS-preflight, сервер должен ответить какие методы/заголовки/origin разрешены.curlэто правило обходит — оно живёт в браузере, а не на сервере. - «Что такое HTTPS, как работает на верхнем уровне?» Тот же HTTP, обёрнутый в TLS. Порт 443, шифруется всё кроме SNI (имя домена в открытом виде), сертификат подтверждает что ты говоришь с настоящим сервером. На уровне приложения работаешь как с обычным HTTP.
Что важно запомнить
HTTP это request/response: метод+путь, заголовки, опционально тело. Методы делятся на идемпотентные (GET/PUT/DELETE) и нет (POST/PATCH).
Пять классов статусов: 1/2/3/4/5xx. На проде чаще всего видишь 502 (прокси не дозвонился) и 504 (бэкенд не успел) — не путай.
HTTPS — тот же HTTP, обёрнутый в TLS и работающий на 443.
HTTP/2 даёт мультиплекс в одном TCP-соединении, HTTP/3 переезжает на UDP/QUIC. На уровне приложения разницы нет, включается опцией прокси.
CORS — правило браузера, не сервера. Из curl не воспроизведёшь.
curl -v показывает handshake, заголовки и ответ — с него удобно начинать
разбор HTTP-проблем.
В следующем уроке — набор утилит, которыми чинят сеть, когда что-то сломалось.
Дрилл · вопросы как на собесе
Проверь себя без подсказок
Сформулируй ответ вслух или письменно, потом раскрой и честно отметь: знал или нет.
Какие методы HTTP бывают?
NET-010Какие коды ответов HTTP бывают?
NET-011Прошли материал до конца? Отметьте урок пройденным.
Прогресс сохранён в этом браузере
Почистишь историю или откроешь с телефона, и отметки пропадут. Оставь почту, они переедут в аккаунт. Пароль придумывать не нужно.
Готово. теперь в аккаунте: прогресс виден с любого устройства. Мой прогресс