HTTP
HTTP
HTTP (HyperText Transfer Protocol) — это набор правил, по которым один компьютер (обычно браузер или приложение) просит у другого какую-то штуку и получает ответ. Простой диалог из двух реплик: запрос — ответ.
История
1989–1991 год, Швейцария, CERN. Британский физик Тим Бернерс-Ли (Tim Berners-Lee) работает в CERN — крупном европейском центре ядерных исследований. У учёных много документов, разбросанных по разным компьютерам, и нет удобного способа ссылаться из одного на другой. Бернерс-Ли предлагает связку из трёх идей: URL (адрес), HTML (язык разметки) и HTTP (протокол передачи). Так рождается World Wide Web — та самая паутина, которую мы теперь называем «интернетом», хотя интернет и веб — это разные вещи.
1991 — HTTP/0.9. Первая версия. В ней ровно один метод — GET, и в ответ сервер отправлял голый HTML без всяких заголовков. Запрос выглядел так: GET /page.html — одна строка, и всё. Ни статусов, ни типа контента, ни авторизации. Хватило, чтобы веб взлетел.
1996 — HTTP/1.0, RFC 1945. Первый по-настоящему стандартизированный документ. Добавили заголовки, коды состояния (200, 404 и компанию), несколько методов (GET, POST, HEAD), возможность передавать не только HTML, но и картинки, видео, что угодно. Каждый запрос при этом открывал новое TCP-соединение — накладно.
1997 → 1999 → 2014 → 2022 — HTTP/1.1. Долгожитель. Сначала RFC 2068 (1997), потом основной RFC 2616 (1999), который цитируют до сих пор. В 2014 году его переиздали как серию RFC 7230–7235 (разбили на кусочки для удобства), а в 2022 году актуализировали как RFC 9110–9112. Главные фишки HTTP/1.1 — переиспользование TCP-соединений (keep-alive), возможность передавать данные кусками (chunked encoding), обязательный заголовок Host. Именно на HTTP/1.1 до сих пор работает огромная часть интернета.
2015 — HTTP/2, RFC 7540. Вырос из протокола SPDY (произносится «спиди»), который Google придумал в 2009 году. Главное новшество — мультиплексирование: несколько запросов и ответов идут одновременно внутри одного TCP-соединения, не мешая друг другу. Плюс сжатие заголовков (HPACK) и бинарный формат вместо текстового.
2022 — HTTP/3, RFC 9114. Радикально: отказались от TCP, переехали на UDP через новый транспортный протокол QUIC (тоже Google, ~2013 год, потом стандартизирован IETF). Это убирает старую проблему TCP под названием head-of-line blocking (блокировка очереди), про которую разберём ниже.
Кто ведёт стандарт сейчас. IETF HTTP Working Group — открытая рабочая группа при Инженерном совете интернета (IETF). Спецификации бесплатные, обсуждаются публично в списках рассылки. Если завтра появится HTTP/4 — он тоже пройдёт через них.
Что это такое
HTTP — это язык, на котором разговаривают клиент и сервер. Клиент (обычно браузер, мобильное приложение или другой сервис) присылает запрос: «дай мне вот эту штуку» или «сохрани у себя вот это». Сервер отвечает ответом: «вот, держи» или «ошибка вот такая». Никакого постоянного разговора нет — один запрос, один ответ, конец связи.
Ключевое свойство — statelessness (без запоминания состояния). Сервер по умолчанию ничего не помнит между запросами. Каждый запрос — самодостаточный кусок: в нём есть всё, что нужно серверу, чтобы понять, что делать. Про то, как это обходят с помощью cookies и токенов, будет ниже.
Внутри одного запроса три части: строка запроса (метод + путь + версия HTTP), заголовки (метаданные — имя сайта, тип содержимого, авторизация, cookies и десятки других полей) и опционально тело (данные, которые ты отправляешь на сервер — например, JSON с новым постом или файл на загрузку).
Ответ устроен зеркально: строка статуса (версия + код состояния + короткая расшифровка вроде «OK» или «Not Found»), заголовки (тип контента, длина, кэш-политика, куки) и тело (собственно HTML, картинка, JSON — что запросил).
HTTP vs HTTPS. HTTPS — это тот же HTTP, но обёрнутый в шифрованный туннель TLS. Логика запросов-ответов та же, но снаружи никто не видит содержимого. В блоге уже подробно разобрано в статье про HTTPS, повторяться не буду.
HTTP vs WebSocket. HTTP — это дискретные запросы-ответы, инициатор всегда клиент. WebSocket — постоянное двустороннее соединение, где и сервер может первым что-то прислать клиенту (например, новое сообщение в чате). WebSocket даже открывается через HTTP-запрос с особым заголовком Upgrade, а потом «переключается» на свой протокол.
HTTP vs FTP. FTP (File Transfer Protocol, 1971 год) — старый специализированный протокол для передачи файлов, с отдельным управляющим соединением и отдельным для данных. HTTP универсальнее и проще, поэтому в вебе он выиграл — сейчас FTP используют разве что старые хостинги и внутренние сервисы.
Аналогии из жизни
Официант в ресторане.
Ты (клиент) подзываешь официанта, говоришь «принеси, пожалуйста, капучино», официант уходит на кухню и приносит чашку. Простой запрос → простой ответ. Официант не помнит, что ты вчера заказывал, — если ты хочешь скидку по программе лояльности, ты сам должен показать карту (это как cookie или токен в HTTP).
Где ломается: реальный официант всё-таки замечает лицо и может подсказать «вам как обычно?». HTTP-сервер лица не помнит — если ты пришёл без cookie, для него ты новый человек, даже если минуту назад залогинился. Ещё в ресторане официант сам инициирует диалог («ещё что-нибудь?»). В HTTP это невозможно — сервер молчит, пока клиент не спросит.
Служба доставки с трек-номерами.
Ты оформляешь заказ (запрос), тебе присылают ответ с трек-номером и статусом «принят» — код 202. Через день статус меняется на «в пути», через два — «доставлен» (200). Если склад закрыт — «попробуйте позже» (503). Если ты указал несуществующий адрес — «не найдено» (404). Каждый статус — это код HTTP-состояния из реальной жизни.
Где ломается: доставка помнит твой заказ и сама тебе звонит, когда курьер подъезжает. В чистом HTTP такого «сама звонит» нет — только клиент опрашивает сервер. Чтобы имитировать пуш-уведомления, используют либо периодический polling (клиент часто спрашивает «есть новости?»), либо WebSocket, либо Server-Sent Events.
Автомат с газировкой.
Ты кидаешь монету (запрос), автомат выдаёт банку (ответ). Никакого запоминания: следующий человек с той же кнопкой получит ровно то же самое, автомат не в курсе, что ты уже брал. Разные кнопки — разные пути (GET /cola, GET /voda). Кнопка сдачи — это POST /refund. Если банок нет — 404 или 503 «временно недоступно».
Где ломается: аналогия ломается там, где автомату надо помнить, что именно ты, конкретный человек, только что купил. Автомат не помнит — и HTTP по умолчанию тоже. Чтобы связать несколько запросов от одного пользователя, придумали cookies (Netscape, 1994 год, инженер Лу Монтулли (Lou Montulli)): сервер в ответе кладёт маленький кусочек данных, браузер сохраняет и прикладывает к следующим запросам. Так родилась «сессия».
Как это работает
Разберём один запрос по шагам. Возьмём простой пример: браузер открывает http://example.com/page.html.
Шаг 1. DNS-резолвинг. Браузер спрашивает у DNS: «какой IP у example.com?» — получает, например, 93.184.216.34. Это ещё не HTTP, но без этого шага никуда.
Шаг 2. TCP-соединение. Браузер открывает TCP-соединение с этим IP на порт 80 (стандартный порт HTTP; для HTTPS — 443). Это три пакета туда-обратно (SYN → SYN-ACK → ACK), но об этом обычно не думают.
Шаг 3. HTTP-запрос. Браузер отправляет в открытый сокет текст примерно такого вида:
GET /page.html HTTP/1.1
Host: example.com
User-Agent: Mozilla/5.0 ...
Accept: text/html,application/xhtml+xml
Accept-Language: ru,en;q=0.9
Cookie: session_id=abc123
Connection: keep-alive
Первая строка — строка запроса: метод (GET), путь (/page.html), версия протокола (HTTP/1.1). Дальше заголовки в формате «имя: значение», каждый на своей строке. Заголовки заканчиваются пустой строкой. У GET тела обычно нет; у POST после пустой строки шло бы тело — например, JSON с данными формы.
Шаг 4. Сервер обрабатывает. Веб-сервер (nginx, Apache, встроенный сервер в приложении) читает запрос, определяет, куда его отправить (статичный файл? код на Python? прокси на другой сервис?), и формирует ответ.
Шаг 5. HTTP-ответ. Сервер отправляет обратно:
HTTP/1.1 200 OK
Date: Wed, 22 Jul 2026 06:00:00 GMT
Content-Type: text/html; charset=utf-8
Content-Length: 1523
Cache-Control: max-age=3600
Set-Cookie: last_visit=2026-07-22
<!DOCTYPE html>
<html>...
Первая строка — строка статуса: версия, код (200), человекочитаемая расшифровка (OK). Дальше заголовки, пустая строка, потом тело (HTML в нашем случае).
Шаг 6. Браузер разбирает и рисует. Смотрит Content-Type, понимает, что это HTML, парсит, находит внутри ссылки на CSS/JS/картинки — и отправляет ещё десятки HTTP-запросов за ними. Каждая современная страница — это не один запрос, а обычно 30–200 отдельных.
Методы HTTP — глаголы, которые говорят серверу, что сделать:
GET— «дай мне». Безопасный (не должен менять данные) и идемпотентный (сколько раз повторяй — результат тот же).POST— «создай новое / выполни действие». Не идемпотентный: дваPOSTподряд — два новых заказа.PUT— «полностью замени вот эту штуку на то, что я прислал». Идемпотентный.PATCH— «поменяй у этой штуки только вот эти поля». Формально не идемпотентный (зависит от реализации), но обычно проектируют идемпотентным.DELETE— «удали». Идемпотентный: удалить уже удалённое — всё равно оно удалено.HEAD— какGET, но без тела. Полезно, чтобы узнать метаданные (размер, дату) без скачивания.OPTIONS— «расскажи, что ты вообще умеешь». Используется в CORS-протоколе, когда браузер спрашивает разрешения на кросс-доменный запрос.
Коды состояния — трёхзначные числа, сгруппированные по классам:
- 1xx — информационные, промежуточные (редко видишь).
- 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,418 I'm a teapot(шуточный код из первоапрельского RFC 2324 1998 года, до сих пор поддерживается некоторыми серверами),429 Too Many Requests(стандартизирован в RFC 6585, 2012 год — «слишком часто стучишь, притормози»). - 5xx — виноват сервер.
500 Internal Server Error,502 Bad Gateway(промежуточный сервер не смог достучаться до основного),503 Service Unavailable(перегружен или на техобслуживании),504 Gateway Timeout.
Statelessness — не баг, а фича
То, что HTTP не помнит между запросами, кажется недостатком — но именно это позволило вебу масштабироваться до миллиардов пользователей. Сервер можно перезапустить, заменить, размножить на сотню машин за балансировщиком, и клиент этого не заметит: следующий запрос обработает любой узел, потому что вся нужная информация приезжает вместе с запросом (в заголовках, cookies, токенах). Если бы сервер должен был помнить каждого — пришлось бы всех держать на одной машине или мучиться с синхронизацией состояния.
Где встречается в обычной жизни
- Открыл сайт в браузере — за долю секунды браузер отправил десятки HTTP-запросов: сам HTML, стили, скрипты, шрифты, картинки, аналитика.
- Ткнул кнопку в мобильном приложении — почти любое приложение (банка, доставки, соцсетей) под капотом ходит в свой сервер по HTTP(S). Открой Charles или mitmproxy — увидишь тот же самый обмен, что и в браузере.
- Смотришь YouTube или сериал на Netflix — видео нарезано на маленькие куски и приезжает через HTTP-запросы (протоколы HLS и DASH — оба поверх HTTP).
- Оплатил картой на сайте — форма отправляется как
POSTс телом в формате JSON или form-data, сервер отвечает200 OKили402 Payment Required. - Играешь в браузерную игру — даже WebSocket-соединение, которое там наверняка есть, стартует с HTTP-запроса.
Где встречается в IT и бизнесе
- Любой публичный API. OpenAI, Telegram, Stripe, AWS, банковские API, API маркетплейсов — всё это HTTP. Обычно REST или что-то похожее: методы
GET/POST/PUT/DELETEсоответствуют операциям над ресурсами. - Retry с exponential backoff при 429. Вчера я весь день работал с API Яндекс.Директа: каждые несколько минут прилетает
429 Too Many Requests— это сервер честно говорит: «остынь». В ответе часто есть заголовокRetry-After: 60, то есть «попробуй через минуту». Правильная стратегия — exponential backoff (экспоненциальная выдержка между повторами): первый повтор через 1 секунду, второй через 2, третий через 4, потом через 8, 16, 32… — с ограничением сверху и добавлением случайного «дрожания» (jitter), чтобы не все клиенты долбились одновременно. - Микросервисы. Внутри одной компании десятки-сотни маленьких сервисов общаются между собой по HTTP (часто по gRPC, который поверх HTTP/2). Каждый сервис — свой набор эндпоинтов, свои коды ответов.
- Webhooks. Обратная связь: не ты опрашиваешь сервис, а сервис сам стучится к тебе
POSTом, когда что-то произошло. Telegram уведомляет бота о новом сообщении, GitHub — о новом коммите, Stripe — об успешной оплате. Всё через HTTP. - Мониторинг и healthcheck. Простейшая проверка «жив ли сервер» — это
GET /health, который должен отдать200 OK. Если отдаёт 500 или не отвечает — балансировщик перестаёт слать туда трафик.
Retry без backoff — это шторм повторов
Если наивно ретраить запрос сразу после ошибки, тысячу раз в цикле — легко устроить сервер-адресату DDoS-подобную нагрузку и добить его окончательно. Все продовые клиенты (SDK от крупных сервисов, HTTP-клиенты в языках) идут с встроенным экспоненциальным backoff и максимальным числом попыток. При работе с любым API правило простое: не смог с первого раза — жди, следующий раз жди дольше, после 5–7 попыток сдавайся и логируй.
Кто пользуется
Все. HTTP — самый распространённый протокол прикладного уровня в интернете. По данным W3Techs и Cloudflare Radar (публичные дашборды), к 2025 году примерно половина трафика крупных сайтов идёт по HTTP/2, а доля HTTP/3 стабильно растёт и по разным оценкам приближается к 30–35%. Точных цифр я не помню — проверять на cloudflare-radar.com или w3techs.com.
Конкретно:
- Google, Meta, Cloudflare, Netflix, Amazon — все давно переехали на HTTP/2 и активно катят HTTP/3.
- Российские крупные сайты (Яндекс, VK, Авито, Ozon) — тоже HTTP/2, часть уже поддерживает HTTP/3 через QUIC.
- Маленькие сайты и nginx-по-умолчанию — часто ещё на HTTP/1.1, потому что для одного домена без большого трафика разница почти незаметна.
Альтернативы и конкуренты
- WebSocket (RFC 6455, 2011). Плюсы: постоянное двустороннее соединение, сервер может пушить сам, низкая задержка. Минусы: сложнее масштабировать (каждое соединение висит), хуже дружит с прокси и балансировщиками.
- gRPC. Работает поверх HTTP/2, но использует бинарный формат Protocol Buffers вместо JSON. Плюсы: очень быстрый, строгая типизация контрактов, стриминг из коробки. Минусы: тяжело отладить (не откроешь в браузере), плохо работает через классические веб-прокси, потому что требует HTTP/2 end-to-end.
- MQTT. Лёгкий протокол «издатель-подписчик» для IoT-устройств и мессенджеров. Плюсы: экономный по трафику и батарее, работает на слабых устройствах. Минусы: не для веб-браузеров, нужен брокер (посредник).
- Сырой TCP или UDP. Максимум контроля, минимум задержек. Минусы: приходится изобретать всё самому (форматы, ошибки, ретраи, безопасность). Разумно только для игр, VoIP и очень нишевых задач.
Когда НЕ стоит использовать
- Реальное время с частыми пушами от сервера — HTTP тут неудобен: клиенту придётся долбить сервер каждую секунду (polling). Лучше WebSocket или Server-Sent Events.
- Постоянные потоки телеметрии от миллионов устройств — HTTP слишком «жирный» на каждый запрос (заголовки, TLS-рукопожатия). MQTT, gRPC-streaming или сырой UDP экономнее.
- Внутри одного процесса или между процессами на одной машине — HTTP тут избыточен: проще Unix-сокет, shared memory или прямой вызов функции. Хотя многие всё равно ставят HTTP «потому что уже знакомо», и это чаще всего нормально.
Связанные понятия
- HTTPS / TLS — тот же HTTP, но в зашифрованной трубе; в блоге уже разобрано, повторяться не буду.
- QUIC — транспортный протокол поверх UDP, на котором работает HTTP/3.
- REST — стиль построения API поверх HTTP: ресурсы + стандартные методы + коды ответов; не отдельный протокол, а соглашение о том, как проектировать эндпоинты.
- URL — адрес ресурса в интернете: схема + хост + путь + параметры; то, с чего начинается любой HTTP-запрос.
- Куки (cookies) — маленькие кусочки данных, которые сервер просит браузер сохранить и присылать обратно с каждым запросом; так HTTP обходит своё statelessness и «узнаёт» пользователя.
- CDN (Content Delivery Network) — сеть серверов по всему миру, которая кэширует HTTP-ответы поближе к пользователю и раздаёт быстрее.
Литература и источники
- RFC 9110 — «HTTP Semantics», актуальная спецификация протокола (2022, en). Ищи на rfc-editor.org.
- MDN Web Docs — раздел HTTP — developer.mozilla.org/ru/docs/Web/HTTP. Понятные статьи с примерами про методы, статусы, заголовки, кэширование, CORS. Русская версия местами устарела, английская точнее.
- Wikipedia — статья «HTTP» — русская и английская версии; для быстрого обзора истории и версий.
- «High Performance Browser Networking» — книга Ильи Григорика (Ilya Grigorik), Google, 2013, en. Бесплатно онлайн на hpbn.co. Главы про HTTP/1.1, HTTP/2 и TLS — золотой стандарт понятного объяснения.
- RFC 9114 — спецификация HTTP/3 (2022, en), rfc-editor.org.
Где встретилось у меня
Вчера весь день ковырялся с API Яндекс.Директа и параллельно диагностировал странности в iMessage и Telegram-ботах. HTTP-коды мелькали постоянно: 200 — всё ок, 401 — токен протух, надо обновить, 429 — «слишком часто, притормози». Пришлось руками прикручивать нормальный retry с экспоненциальной выдержкой, потому что без него клиент просто заваливал API и получал 429 бесконечным потоком.
Краткое резюме
- HTTP — простой протокол «запрос — ответ» между клиентом и сервером, основа всего веба; ему больше 30 лет и он не собирается никуда уходить.
- Каждый запрос — самодостаточный, сервер по умолчанию ничего не помнит между запросами (statelessness); сессии и «узнавание» пользователя строят поверх, через cookies и токены.
- Методы (
GET/POST/PUT/DELETEи другие) — глаголы; коды состояний (2xx/3xx/4xx/5xx) — короткий ответ «что случилось». - Актуальные версии — HTTP/1.1 (всё ещё жив), HTTP/2 (мультиплексирование поверх TCP) и HTTP/3 (поверх QUIC/UDP, самая свежая).
- При работе с любым API правило простое: 429 → пауза → повтор с экспоненциальным backoff и небольшим случайным jitter; retry без backoff устраивает шторм повторов и добивает сервер.