Отличия HTTP/1.0, 1.1, 2 и 3: протокол и транспорт

Чем отличаются 1.0, 1.1, 2.0, 3.0 версии HTTP?

Теория: что сравнивается

Семантика против “провода”

HTTP описывает архитектуру request/response, роли клиента/сервера и общий формат сообщений.
Начиная с HTTP/2, принципиально меняется не “смысл HTTP”, а его представление на уровне передачи: появляются бинарные кадры, сжатие заголовков, параллельные обмены.
HTTP/3 продолжает этот подход: это перенос тех же смыслов HTTP на другой транспорт (QUIC), при котором часть задач (потоки, контроль потока, восстановление потерь, безопасность) “спускается” в транспортный уровень.

Что обычно отличают на практике

При сравнении версий HTTP обычно оцениваются: стоимость установления соединения, возможность параллельной загрузки, накладные расходы заголовков, устойчивость к head-of-line blocking, поведение через прокси/балансировщики.
В HTTP/1.1 сообщение определяется как стартовая строка + заголовки + пустая строка + опциональное тело, и парсинг должен быть строго “по байтам”, иначе возможны неоднозначности и уязвимости.

HTTP/1.0 и HTTP/1.1

HTTP/1.0: “одно соединение — один запрос”

HTTP/1.0 исторически часто воспринимается как модель “клиент открыл TCP-соединение → сделал запрос → получил ответ → соединение закрыто”, из‑за чего серия запросов к странице (HTML, CSS, изображения) приводила к множеству соединений и лишним задержкам.
Протокол закрепляет парадигму request/response: запрос содержит метод, URI и версию протокола, затем MIME‑подобные заголовки и возможное тело; ответ содержит статусную строку, заголовки и возможное тело.
В HTTP/1.0 встречались “терпимые” реализации, но уже на этом уровне важно избегать двусмысленных конструкций в заголовках.

Пример обмена в стиле HTTP/1.0 (показан принцип, когда после ответа соединение логически завершается):

GET /index.html HTTP/1.0
User-Agent: demo-client

HTTP/1.0 200 OK
Content-Type: text/html
Content-Length: 13

Hello, world!

HTTP/1.1: стандартная база 1.x и более строгая маршрутизация/синтаксис

HTTP/1.1 фиксирует строгие требования к разбору сообщений и маршрутизации, включая то, что HTTP-сообщение должно парситься как последовательность октетов (а не как “строки”), иначе возникают риски неоднозначной интерпретации переводов строк и разделителей.
В HTTP/1.1 одно TCP-соединение может переиспользоваться для нескольких последовательных обменов request/response, что экономит время и ресурсы по сравнению с “под каждый запрос отдельное соединение”.
HTTP/1.1 также стандартизирует и уточняет множество деталей совместимости и поведения промежуточных узлов (прокси, шлюзов).

Пример “типичного” HTTP/1.1-запроса с обязательным Host и версией в стартовой строке:

GET /hello.txt HTTP/1.1
Host: www.example.com
User-Agent: demo-client
Accept-Language: en

HTTP/1.1 200 OK
Content-Type: text/plain
Content-Length: 5

Hello
На уровне HTTP/1.1 наиболее частые проблемы безопасности и совместимости возникают из‑за неправильного/слишком “терпимого” парсинга запросов и ответов на границе прокси/балансировщиков, поэтому корректная обработка разделителей, длины тела и некорректных сообщений критична.

HTTP/2: бинарный фрейминг и мультиплексирование

Главная идея HTTP/2

HTTP/2 — оптимизированный способ “выразить” семантику HTTP на проводе так, чтобы эффективнее использовать сеть и уменьшить задержки загрузки.
Ключевые механизмы: бинарный фрейминг, мультиплексирование потоков в одном соединении, сжатие заголовков, а также server push (исторически — спорная функция, так как на практике может быть неэффективной при неправильном применении).
HTTP/2 не отменяет смысловую модель HTTP/1.1: методы, статусы, URI и большинство заголовков остаются теми же, меняется способ передачи.

Потоки (streams) и кадры (frames)

Одно HTTP/2-соединение содержит несколько потоков (streams), а данные передаются кадрами (frames); кадры разных потоков могут перемежаться в одном соединении.
Внутри каждого потока порядок кадров важен: например, сначала идут заголовки, затем данные, и получатель должен соблюдать правила состояния потока.
HTTP/2 работает с теми же схемами URI http/https и теми же портами по умолчанию (80/443), а включение HTTP/2 требует механизма обнаружения/переговоров.

Negotiation: ALPN и Upgrade

Для TLS-варианта HTTP/2 идентификатор протокола в ALPN — h2.
Для варианта поверх “чистого” TCP используется h2c, и он может согласовываться через заголовки Upgrade/HTTP2-Settings, если старт происходит как HTTP/1.1.

Мини-пример попытки апгрейда до h2c (показан общий вид):

GET / HTTP/1.1
Host: server.example.com
Connection: Upgrade, HTTP2-Settings
Upgrade: h2c
HTTP2-Settings: <base64url-encoding-of-settings>

HTTP/1.1 101 Switching Protocols
Connection: Upgrade
Upgrade: h2c

<далее идут HTTP/2 frames>

HTTP/3: HTTP поверх QUIC (UDP)

Что такое QUIC в контексте HTTP/3

QUIC — транспорт поверх UDP, который даёт приложению концепцию потоков (streams), мультиплексирование, контроль потока, восстановление потерь, а также криптографическую защиту и ускоренное установление соединения по сравнению с классической связкой TCP+TLS.
В QUIC безопасность и согласование ключей тесно интегрированы с установлением соединения, что уменьшает количество “шагов” до начала передачи данных.
HTTP/3 использует эти свойства QUIC, чтобы снизить взаимные блокировки между параллельными запросами и лучше переживать потери/переключения сетевых путей.

HTTP/3 как “маппинг” поверх QUIC

HTTP/3 описывает отображение семантики HTTP на QUIC и во многом наследует идеи HTTP/2, но делегирует QUIC жизненный цикл потоков и контроль потока.
HTTP/3 опирается на QUIC для конфиденциальности/целостности, аутентификации пира и надёжной, упорядоченной доставки в рамках каждого потока.
Для выбора HTTP/3 при TLS‑переговорах используется ALPN‑токен h3.

Строгость к ошибкам и контрольные потоки

HTTP/3 требует от промежуточных узлов не пересылать некорректно сформированные запросы/ответы и трактует malformed сообщения как ошибку потока определённого типа.
Каждая сторона должна открыть control stream и отправить SETTINGS первым кадром на нём; нарушение этого правила считается ошибкой соединения.

Пример (схематично) установления:

DNS/адрес
  ↓
QUIC handshake + TLS (ALPN: h3)
  ↓
Создание control stream
  ↓
SETTINGS frame (первым)
  ↓
Request streams (параллельно, независимо)

Практика: таблицы, схемы, примеры и ответы

Таблица отличий (суть)

ВерсияТранспортФормат “на проводе”ПараллелизмКлючевой выигрышТиповая проблема
HTTP/1.0TCPТекстовые строки + заголовкиВ основном последовательно; часто новое соединение под запросПростота и совместимостьВысокая цена множества соединений и задержек на установление
HTTP/1.1TCPТекстовые сообщения со строгим парсингомНесколько обменов в одном соединении (последовательно)Переиспользование соединения, единые правилаУязвимости/ошибки из‑за неправильного парсинга и “терпимых” прокси
HTTP/2Обычно TCP (часто через TLS)Бинарные frames, streamsМультиплексирование потоков в одном соединенииМеньше задержек, эффективнее сеть, сжатие заголовков, pushHOL на уровне TCP при потерях пакетов сохраняется
HTTP/3QUIC поверх UDP (+TLS внутри QUIC)Бинарная модель поверх QUIC-streamsМультиплексирование с независимыми потокамиМеньше HOL между потоками, быстрее старт, миграция путиUDP может фильтроваться, инфраструктуру необходимо настроить
Полезно воспринимать HTTP/2 и HTTP/3 как разные “упаковки” одних и тех же HTTP-смыслов: меняется не то, что означает запрос/ответ, а то, как они кодируются и доставляются.

Мини-примеры: “как выглядит” различие

HTTP/1.1 — читаемый текст с разделением заголовков и тела:

GET /resource HTTP/1.1
Host: example.com
Accept: text/html

HTTP/1.1 200 OK
Content-Type: text/html
Content-Length: 3

ok!

HTTP/2 — после согласования идут бинарные кадры, а один канал содержит много потоков, кадры потоков перемежаются:

[STREAM 1] HEADERS
[STREAM 3] HEADERS
[STREAM 1] DATA chunk #1
[STREAM 3] DATA chunk #1
[STREAM 1] DATA chunk #2
...

HTTP/3 — похожая идея потоков, но транспорт QUIC сам даёт streams/flow-control и безопасность, поэтому HTTP/3 описывает отображение HTTP поверх QUIC:

QUIC stream (request) -> HTTP request mapping
QUIC stream (response)-> HTTP response mapping
Control stream -> SETTINGS first

Кратко: HTTP/1.0, HTTP/1.1, HTTP/2 и HTTP/3 передают одни и те же базовые HTTP-смыслы (методы, статусы, заголовки, URI), но существенно отличаются тем, как кодируются и доставляются сообщения по сети, а также тем, как устроены соединения и параллелизм.
Ключевая эволюция: от простого текстового формата и частых TCP-соединений (1.0) к устойчивым соединениям и более строгим правилам (1.1), затем к бинарному фреймингу и мультиплексированию в одном соединении (2), и далее — к переносу HTTP поверх QUIC/UDP с меньшими задержками установления и лучшей устойчивостью к блокировкам (3).