Перейти к содержанию

HTTP

HTTP (HyperText Transfer Protocol) - протокол прикладного уровня, по которому клиент и сервер обмениваются запросами и ответами.

  • Запрос-ответ. Клиент спрашивает, сервер отвечает. Сам сервер обмен не начинает: толкнуть данные клиенту без запроса - это WebSocket, SSE, long polling (см. Communication & API Style).
  • Stateless. Каждый запрос самостоятельный, сервер не помнит предыдущие. Состояние между запросами держат cookies и токены (см. AUTH).
  • Версии. HTTP/1.1 и HTTP/2 работают поверх TCP, HTTP/3 - поверх QUIC (UDP). Методы, заголовки и коды ответов у всех версий одни.
  • HTTPS. Тот же HTTP внутри TLS (см. TLS).

REST - стиль API поверх HTTP: ресурсы, методы, коды ответов.


URI и URL

URI (Uniform Resource Identifier) - идентификатор ресурса. URL (Uniform Resource Locator) - URI, который ещё и говорит, где ресурс лежит и как его достать. URN (Uniform Resource Name) - URI-имя без адреса.

Note

Каждый URL - это URI, обратное неверно. urn:isbn:9780306406157 называет книгу, но не говорит, где её взять.

https://api.example.com:8443/books/42?author=name#reviews
└─┬─┘   └────────┬─────────┘└───┬───┘ └────┬────┘ └──┬──┘
scheme       authority        path       query   fragment

Fragment браузер на сервер не отправляет: он нужен только клиенту (якорь на странице, роутинг SPA).

Аспект URI URL
Цель Однозначно идентифицировать ресурс в абстрактном пространстве имён Указать сетевой механизм доступа и расположение ресурса
Схема Любая, в том числе не сетевая: urn:, tel:, data: Сетевые протоколы: http:, https:, ftp:, ws:
Локатор? Может быть, но не обязан. Пример без локации - URN Всегда содержит информацию «где» и «как»
Компоненты scheme:[//authority]path[?query][#fragment], authority необязателен У сетевых схем есть scheme://authority/path, query и fragment опциональны
Примеры urn:isbn:9780306406157 (книга)
tel:+49-30-1234567 (номер телефона)
ftp://ftp.kernel.org/pub/linux/README
https://github.com/user/repo.git
Использование XML Namespaces, RDF, SIP-адреса (sip:) Ссылки в HTML, API-эндпоинты, загрузка файлов
Стандарт RFC 3986 (общие правила), RFC 8141 (URN) Тот же RFC 3986 и отдельные RFC для схем (http, ftp и тд)

Запрос и ответ

Из чего состоит сообщение

Запрос и ответ устроены одинаково:

  1. Стартовая строка. У запроса метод URI версия: GET /books?author=name HTTP/1.1. У ответа версия код фраза: HTTP/1.1 200 OK.
  2. Заголовки. Строки Имя: значение: тип тела, авторизация, кэш, cookies.
  3. Пустая строка. Конец заголовков.
  4. Тело. Необязательное, его тип задаёт Content-Type.

В HTTP/2 и HTTP/3 сообщение идёт бинарными фреймами, а заголовки сжимаются (HPACK, QPACK), но поля те же.

Увидеть сырой обмен: curl -v https://example.com. Строки с > - запрос, с < - ответ.

Пример:

POST /books?draft=true HTTP/1.1
Host: api.example.com
Content-Type: application/json
Authorization: Bearer eyJhbGciOi...
Cookie: sessionid=abc123

{"author": "name", "title": "book1"}
HTTP/1.1 201 Created
Content-Type: application/json
Location: /books/42
Set-Cookie: theme=dark; Path=/

{"id": 42, "author": "name", "title": "book1"}

Как передать данные

Канал Клиент -> сервер Сервер -> клиент Пример
Путь да нет /books/42
Query да нет /book?author=name
Body да да {"author": "name", "title": "book1"}, JSON или XML
Заголовки да да Authorization: Bearer ..., Location: /books/42
Cookies Cookie Set-Cookie Cookie: sessionid=abc123
Статус-код нет да 201 Created
  • Query часто зовут GET-параметрами, но строка запроса есть у любого метода. Она оседает в логах серверов и в истории браузера, поэтому пароли и токены в query не кладут.
  • Body у GET по стандарту без смысла: RFC 9110 не задаёт его семантику, и прокси или сервер может такой запрос отклонить. Параметры GET передают в query.
  • Cookies - тоже заголовки. Сервер ставит Set-Cookie, браузер хранит cookie и сам шлёт её в Cookie с каждым запросом на этот домен. На этом держатся сессии (см. AUTH).

Content-Type

Content-Type - заголовок с типом тела в формате тип/подтип (MIME-тип, media type). Бывают параметры: charset для текста, boundary для multipart.

Content-Type: text/html; charset=utf-8
Content-Type: multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxk
  • Клиент пишет тип своего тела в Content-Type, а какой ответ примет - в Accept. Сервер не понимает тип тела -> 415, не может отдать нужный тип -> 406.
  • Суффикс +json или +xml значит, что формат построен поверх JSON или XML и читается обычным парсером: application/problem+json.
  • Префикс x- - нестандартный тип, не зарегистрированный в IANA: application/x-ndjson. vnd. - тип вендора: application/vnd.ms-excel.

Самые частые: в API - application/json, multipart/form-data, application/x-www-form-urlencoded, text/plain. Для страниц - text/html, text/css, text/javascript и картинки. В таблицах они жирные.

JSON

Тип Что это
application/json Основной формат обмена данными в REST, GraphQL и вебхуках. Во фронтенде читается встроенным JSON.parse, на сервере - любым фреймворком
application/ld+json JSON-LD (Linked Data)
application/schema+json JSON Schema
application/geo+json GeoJSON, геоданные
application/csp-report JSON-отчёты о нарушениях Content Security Policy

XML

Тип Что это
application/xml Обычный XML
application/rss+xml RSS-ленты
application/atom+xml Atom-фиды
application/mathml+xml MathML, математические формулы
application/xslt+xml XSLT, трансформация XML
application/xhtml+xml XHTML

Текст

Тип Что это
text/plain Обычный текст
text/csv Табличные данные через запятую (CSV)
text/tab-separated-values Табличные данные через табуляцию (TSV)
text/html Веб-страницы. При переходе по ссылке браузер по умолчанию ждёт HTML
text/css Таблицы стилей. С другим типом браузер стили не применит. Кэшируется надолго, от него зависит скорость загрузки страницы
text/javascript JS: логика клиента, React, Vue, аналитика, на нём держатся SPA. Актуальный тип по RFC 9239 (2022), application/javascript устарел, но встречается повсюду
text/markdown Markdown

Формы и multipart

Тип Что это
application/x-www-form-urlencoded Тип по умолчанию у HTML-формы: key=value&key2=value2. Поиск, логин, фильтры. Любой бэкенд-фреймворк разбирает без настроек
multipart/form-data Загрузка файлов через <form>: аватары, документы. Текстовые поля и бинарные части в одном запросе, части разделены строкой boundary
multipart/mixed Несколько частей разных типов, например JSON + файл
multipart/alternative Альтернативные версии одного контента, например HTML + текст
multipart/related Взаимосвязанные части, например HTML + его картинки
multipart/signed Контент с цифровой подписью
multipart/encrypted Зашифрованные данные

Бинарные данные, архивы, документы

Тип Что это
application/octet-stream Бинарные данные неизвестного формата. Браузер их скачивает
application/pdf PDF
application/zip ZIP
application/gzip GZIP
application/x-bzip2 BZIP2
application/x-tar TAR
application/x-7z-compressed 7Z
application/x-rar-compressed RAR. Зарегистрированный тип - application/vnd.rar
application/vnd.android.package-archive APK, приложение Android
application/msword Word (.doc)
application/vnd.openxmlformats-officedocument.wordprocessingml.document Word (.docx)
application/vnd.ms-excel Excel (.xls)
application/vnd.openxmlformats-officedocument.spreadsheetml.sheet Excel (.xlsx)
application/vnd.ms-powerpoint PowerPoint (.ppt)
application/vnd.openxmlformats-officedocument.presentationml.presentation PowerPoint (.pptx)

Картинки

PNG, JPEG и WebP - основные растровые форматы сайтов: лого, фото, иконки. Картинки дают большую часть веса страницы.

Тип Что это
image/png PNG
image/jpeg JPEG
image/gif GIF
image/webp WebP
image/svg+xml SVG, векторная графика в XML. Других типов у SVG нет, application/svg+xml не существует
image/bmp BMP
image/tiff TIFF
image/x-icon ICO, фавиконка

Аудио и видео

Тип Что это
audio/mpeg MP3
audio/wav WAV
audio/ogg OGG
audio/flac FLAC
audio/aac AAC
video/mp4 MP4
video/webm WebM
video/ogg Ogg Video
video/x-msvideo AVI
video/x-matroska MKV

Шрифты

Тип Что это
font/ttf TTF
font/woff WOFF
font/woff2 WOFF2

Типы font/* появились в RFC 8081 (2017). Старые application/x-font-ttf, application/x-font-woff и подобные ещё встречаются в конфигах серверов.

Для API

Тип Что это
application/graphql Сырой текст GraphQL-запроса. В спецификации GraphQL over HTTP его нет: запрос идёт как application/json, ответ - application/graphql-response+json
application/x-ndjson Поток JSON, один объект на строку (Newline Delimited JSON)
application/vnd.api+json JSON:API, спецификация формата REST API на JSON
application/problem+json Ошибка API в JSON по RFC 9457 (Problem Details): поля type, title, status, detail
application/problem+xml То же в XML

Прочее

Тип Что это
application/x-pem-file PEM-файл: ключи и сертификаты TLS в Base64 (см. TLS)
application/x-httpd-php PHP-код. Этим типом Apache помечает файлы, которые выполняет PHP. Клиент получает уже результат, обычно text/html
application/vnd.apple.installer+xml Установщик macOS

Коды ответов

Код - три цифры, первая задаёт класс. Клиент, который не знает конкретный код, обрабатывает его как x00 своего класса: неизвестный 432 - как 400. (WebDAV) - код из расширения WebDAV (RFC 4918), в обычных API почти не встречается.

Посмотреть код ответа: curl -s -o /dev/null -w '%{http_code}' https://example.com.

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

Код Фраза Что значит
100 Continue Клиент может продолжать отправку тела запроса
101 Switching Protocols Сервер переходит на другой протокол (WebSocket и др.)
102 Processing (WebDAV) Долгая операция ещё выполняется. Устарел
103 Early Hints Заголовки-подсказки (Link) до окончательного ответа

2xx: успех

Код Фраза Что значит
200 OK Запрос успешен
201 Created Создан новый ресурс
202 Accepted Принят в обработку, результата пока нет
203 Non-Authoritative Information Прокси изменил исходный ответ
204 No Content Тела нет, но всё ОК
205 Reset Content Очистить формы на клиенте
206 Partial Content Фрагмент ресурса по заголовку Range
207 Multi-Status (WebDAV) Множественные результаты по коллекции
208 Already Reported (WebDAV) Узел уже был отражён ранее
226 IM Used Ответ содержит delta-обновление (RFC 3229)

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

Код Фраза Что значит
300 Multiple Choices Несколько вариантов
301 Moved Permanently Постоянный редирект
302 Found Временный редирект (исторически «Moved Temporarily»)
303 See Other Перейти по другому URI методом GET (POST -> GET)
304 Not Modified Кэш актуален (ETag, Last-Modified)
305 Use Proxy Требовался прокси. Устарел
306 (Unused) Зарезервировано
307 Temporary Redirect Временный, сохраняет метод
308 Permanent Redirect Постоянный, сохраняет метод

Note

При 301 и 302 браузеры исторически превращают POST в GET. 307 и 308 сохраняют метод и тело. 303 - явное «теперь сделай GET сюда»: им отвечают на POST формы, чтобы обновление страницы не отправило форму повторно (Post/Redirect/Get).


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

Код Фраза Что значит
400 Bad Request Синтаксическая ошибка, запрос не разобрать
401 Unauthorized Требуется аутентификация
402 Payment Required Зарезервирован (часто для квот и платежей)
403 Forbidden Доступ запрещён
404 Not Found Ресурс не найден
405 Method Not Allowed Ресурс не поддерживает этот метод
406 Not Acceptable Нет представления, подходящего под Accept
407 Proxy Authentication Required Нужна аутентификация на прокси
408 Request Timeout Клиент слишком медленный или молчит
409 Conflict Конфликт с текущим состоянием ресурса
410 Gone Ресурс удалён без возврата
411 Length Required Нет Content-Length, а он обязателен
412 Precondition Failed Нарушены условия If-*
413 Content Too Large Тело превышает лимит. До RFC 9110 назывался Payload Too Large
414 URI Too Long URI длиннее, чем сервер готов обработать
415 Unsupported Media Type Неподдерживаемый Content-Type
416 Range Not Satisfiable Диапазон вне ресурса
417 Expectation Failed Expect: 100-continue не выполнено
418 I'm a teapot Пасхалка, первоапрельский RFC 2324
421 Misdirected Request Запрос попал на сервер, который не обслуживает этот хост (переиспользованное соединение HTTP/2)
422 Unprocessable Content Синтаксис верный, но данные семантически неверны. Пришёл из WebDAV как Unprocessable Entity, с RFC 9110 общий
423 Locked (WebDAV) Ресурс заблокирован
424 Failed Dependency (WebDAV) Предыдущее действие провалилось
425 Too Early Сервер не обрабатывает запрос из TLS early data (0-RTT): злоумышленник может его переиграть (replay)
426 Upgrade Required Перейдите на другой протокол
428 Precondition Required Требуются If-Match или If-Unmodified-Since
429 Too Many Requests Лимит запросов (rate limit)
431 Request Header Fields Too Large Слишком большие заголовки
451 Unavailable For Legal Reasons Блокировка по закону (DMCA, суд)

Note

Частая путаница:

  • 401 и 403. 401 - сервер не знает, кто ты: учётных данных нет или они неверны, в ответе WWW-Authenticate.

    403 - знает, но прав нет, повторный логин не поможет.

  • 400 и 422. 400 - запрос не разобрать: битый JSON, кривой заголовок. 422 - разобрали, но данные не > проходят валидацию.
  • 405 и 501. 405 - сервер знает метод, но этот ресурс его не принимает, в ответе Allow. 501 - сервер не > умеет метод вообще.
  • 404 и 410. 404 - ресурса нет, и неизвестно, был ли. 410 - был и не вернётся.

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

Код Фраза Что значит
500 Internal Server Error Общее «что-то сломалось»
501 Not Implemented Сервер вообще не умеет этот метод или функцию
502 Bad Gateway Прокси или шлюз получил неверный ответ от апстрима
503 Service Unavailable Сервис временно недоступен (обслуживание, перегрузка)
504 Gateway Timeout Апстрим не ответил вовремя
505 HTTP Version Not Supported Версия протокола не поддерживается
506 Variant Also Negotiates Ошибка настройки content negotiation на сервере
507 Insufficient Storage (WebDAV) Недостаточно места
508 Loop Detected (WebDAV) Бесконечный цикл при обработке дерева ресурсов
510 Not Extended Требуются дополнительные расширения запроса (RFC 2774)
511 Network Authentication Required Нужно залогиниться в сети: captive portal в Wi-Fi

Кэширование (заголовки ответа Cache-Control, Expires, ETag)