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 и тд) |
Запрос и ответ¶
Из чего состоит сообщение¶
Запрос и ответ устроены одинаково:
- Стартовая строка. У запроса
метод URI версия:GET /books?author=name HTTP/1.1. У ответаверсия код фраза:HTTP/1.1 200 OK. - Заголовки. Строки
Имя: значение: тип тела, авторизация, кэш, cookies. - Пустая строка. Конец заголовков.
- Тело. Необязательное, его тип задаёт 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 |
|
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 |