Как читать HTTP-запросы и ответы без путаницы в методах и кодах

1116
Как читать HTTP-запросы и ответы без путаницы в методах и кодах

HTTP-запрос сообщает серверу, с каким ресурсом клиент хочет работать и какой результат ожидает. Метод задает смысл операции, адрес выбирает ресурс, заголовки передают условия обмена, а необязательное тело содержит данные. Сервер отвечает кодом состояния, собственными заголовками и, когда требуется, содержимым.

Как читать HTTP-запросы и ответы без путаницы в методах и кодах

Главная ошибка при изучении HTTP заключается в попытке связать каждый элемент с одной бытовой задачей. POST не означает только создание записи, PUT не означает любое обновление, а код 200 не подходит для каждого успешного ответа. HTTP задает семантику обмена, а приложение уже решает, как связать протокол с заказами, файлами, пользователями или платежами. Общую модель определяют RFC 9110 и руководство MDN.

Из каких частей состоит HTTP-сообщение

В HTTP/1.1 запрос начинается со строки запроса. После нее идут поля заголовков, пустая строка и необязательное тело. Структуру фиксируют RFC 9112 и справочник MDN.

POST /api/orders?notify=true HTTP/1.1
 Host: example.com
 Content-Type: application/json
 Accept: application/json
 Authorization: Bearer eyJhbGciOi... 
 Content-Length: 47
 
 {"product_id":137,"quantity":2,"color":"black"}

Первая строка содержит метод POST, цель запроса /api/orders?notify=true и версию HTTP/1.1. Метод чувствителен к регистру, поэтому стандартные имена пишут прописными буквами. Цель запроса в наиболее распространенной форме содержит путь и необязательную строку параметров. Правила описывают RFC 9112 и руководство MDN.

Поле Host указывает адресата запроса. Один сервер или IP-адрес может обслуживать несколько доменов, поэтому HTTP/1.1 требует передавать Host. Сервер обязан вернуть 400 Bad Request, если поле отсутствует, имеет некорректное значение или встречается более одного раза. Требование содержат RFC 9112 и документация MDN.

Content-Length задает длину тела в байтах, а не количество видимых символов. В приведенном JSON все символы входят в ASCII, поэтому 47 символов занимают 47 байт. Кириллица в UTF-8 обычно занимает больше одного байта на символ. Семантику поля подтверждают RFC 9110 и справка MDN.

Ответ HTTP/1.1 строится похожим образом.

HTTP/1.1 201 Created
 Content-Type: application/json
 Content-Length: 43
 Location: /api/orders/9821
 Cache-Control: no-store
 
 {"id":9821,"status":"created","total":3198}

Строка статуса содержит версию протокола, трехзначный код и необязательную поясняющую фразу. Клиент должен принимать решения по числовому коду, а не по словам Created или Not Found. Синтаксис задают RFC 9112 и руководство MDN.

HTTP/2 не передает текстовую строку запроса. Протокол разбивает сообщения на бинарные кадры, сжимает поля через HPACK и передает служебные значения в псевдозаголовках. HTTP/3 сохраняет семантику HTTP, но работает поверх QUIC и использует QPACK. Механизмы описывают RFC 9113, RFC 9114, справки HTTP/2 и HTTP/3.

:method: GET
 :scheme: https
 :authority: example.com
 :path: /api/orders/9821
 accept: application/json

Псевдозаголовки не являются произвольными пользовательскими полями. Они заменяют данные, которые HTTP/1.x переносит в строке запроса или строке статуса. Ответ HTTP/2 и HTTP/3 передает код через :status, без текстовой фразы OK или Created.

Разные трактовки границ HTTP/1.1 между прокси и конечным сервером могут привести к request smuggling. Проблему обычно вызывают конфликты в обработке Content-Length, Transfer-Encoding или ошибки преобразования HTTP/2 в HTTP/1.1, а не просто пропущенная пустая строка. Причины разбирают RFC 9112 и исследовательская база PortSwigger.

Материал предназначен для легальной диагностики собственных систем. Проверки нельзя применять для несанкционированного доступа, вмешательства в чужой трафик, слежки или нарушения правил сервисов и законов своей страны, включая Россию.

Что на самом деле означают методы

Метод Назначение Безопасный Идемпотентный
GET Получить представление ресурса Да Да
HEAD Получить ответ как для GET, но без содержимого Да Да
POST Передать данные для обработки по правилам ресурса Нет Нет
PUT Создать или заменить состояние ресурса по известному адресу Нет Да
PATCH Применить частичное изменение Нет Не гарантируется
DELETE Удалить связь между URI и текущей функциональностью ресурса Нет Да
OPTIONS Узнать параметры взаимодействия с ресурсом или сервером Да Да
CONNECT Создать туннель через посредника Нет Нет
TRACE Получить диагностическое отражение запроса Да Да
QUERY Передать запрос в теле без изменения состояния ресурса Да Да

Классификацию методов задают RFC 9110 и реестр IANA. Безопасный метод не должен менять бизнес-состояние по намерению клиента. Сервер при этом вправе записать обращение в журнал, обновить статистику или увеличить счетчик просмотров.

Идемпотентность означает одинаковое целевое состояние после одного и нескольких одинаковых запросов. Повторный PUT с тем же представлением обычно оставляет ресурс в том же состоянии. Повторный POST может создать второй платеж или заказ. Ответы при повторении идемпотентной операции не обязаны совпадать. Первый DELETE может вернуть 204, а второй 404, хотя ресурс после обоих запросов отсутствует. Определение подтверждают RFC 9110 и справка MDN.

POST не означает только создание, а PUT не означает любое обновление. POST просит целевой ресурс обработать содержимое по собственной логике. PUT предполагает, что клиент знает адрес ресурса и передает его новое состояние. PATCH применяет изменение, формат которого задает используемый медиатип. Различия описывают RFC 9110 и справочники PUT и PATCH.

DELETE не гарантирует физическое уничтожение всех связанных данных. Сервер может архивировать запись, сохранить резервную копию или оставить внутреннюю историю. Метод выражает намерение удалить сопоставление ресурса с указанным URI.

Метод QUERY стал стандартом в июне 2026 года. QUERY позволяет передавать сложные параметры в теле, оставаясь безопасным и идемпотентным. Поддержка в серверах, прокси, библиотеках и кешах только формируется, поэтому заменять привычные GET и POST без проверки инфраструктуры рано. Статус метода подтверждают RFC 10008 и реестр IANA.

Как не перепутать заголовки, параметры и тело

Поле HTTP состоит из имени и значения. Имена полей регистронезависимы, поэтому Content-Type и content-type обозначают одно поле. HTTP/2 и HTTP/3 требуют передавать имена обычных полей в нижнем регистре. Правила приводят RFC 9110 и справочник MDN.

Поле Назначение
Content-Type Формат содержимого текущего сообщения
Accept Форматы ответа, которые принимает отправитель
Authorization Учетные данные или токен доступа
Cookie Сохраненные клиентом данные сеанса
Set-Cookie Команда сохранить или изменить cookie
Cache-Control Правила кеширования
ETag Идентификатор версии представления
If-Match Условие для безопасного изменения известной версии
If-None-Match Условие для проверки актуальности кеша
Location Адрес созданного ресурса или цель перенаправления
Content-Length Длина содержимого в байтах

Content-Type описывает отправленное содержимое, а Accept перечисляет подходящие форматы ответа. Сервер может вернуть 415 Unsupported Media Type, если не поддерживает формат тела, и 406 Not Acceptable, если не может сформировать приемлемое представление. Семантику полей подтверждают RFC 9110, справки Content-Type и Accept.

curl -i https://example.com/api/users 
   -H "Accept: application/json"
 
 curl -i https://example.com/api/users 
   -X POST 
   -H "Content-Type: application/json" 
   -H "Accept: application/json" 
   --data '{"name":"Anna","role":"editor"}'

Строка запроса начинается после знака ? и входит в URI.

GET /search?q=http&page=2&sort=date HTTP/1.1

Тело идет после полей и пустой строки. JSON, данные HTML-формы, файл и двоичный поток относятся к содержимому сообщения. HTTP не задает общей семантики для содержимого GET, поэтому серверы, клиенты и посредники могут отклонить или проигнорировать такой запрос. Для совместимого API лучше использовать параметры URI, POST или QUERY при подтвержденной поддержке. Ограничение описывают RFC 9110 и справка MDN.

Поле Authorization само по себе не шифрует токен. Bearer-токен получает любой участник, который смог его прочитать, поэтому такие запросы требуют защищенного TLS-канала. Пароли, API-ключи и токены не следует помещать в URL. Рекомендации дают RFC 6750 и памятка OWASP.

Для предотвращения потерянных обновлений сервер может вернуть ETag, а клиент при изменении отправить If-Match. Если версия уже изменилась, сервер отвечает 412 Precondition Failed вместо перезаписи чужих правок. Механизм описывают RFC 9110 и руководство MDN.

Как выбирать и диагностировать коды состояния

Класс Смысл Примеры
1xx Промежуточная информация 100, 103
2xx Запрос успешно обработан 200, 201, 204
3xx Перенаправление или работа с кешированной копией 301, 304, 307
4xx Сервер обнаружил проблему в запросе клиента 400, 404, 429
5xx Сервер или посредник не смог обработать запрос 500, 502, 503

Классы и официальный список кодов определяют RFC 9110 и реестр IANA.

200 OK сообщает об успешном запросе. 201 Created подходит для созданного ресурса и часто сопровождается полем Location. 202 Accepted означает, что сервер принял задачу, но еще не завершил обработку. 204 No Content подтверждает успех без содержимого ответа. Определения подтверждают RFC 9110 и справочник MDN.

301 и 308 обозначают постоянное перенаправление, 302 и 307 обозначают временное. Коды 307 и 308 сохраняют метод и тело. Браузеры часто заменяют POST на GET после 301 или 302. Код 303 See Other прямо требует перейти к новому адресу методом GET. Правила приводят RFC 9205 и руководство MDN.

304 Not Modified не является обычным переходом на другой адрес. Сервер сообщает, что условный GET или HEAD может использовать сохраненную копию. Ответ 304 не содержит тела. Поведение описывают RFC 9110 и справка MDN.

400 Bad Request подходит для некорректного синтаксиса или framing. 401 Unauthorized сообщает об отсутствующих или неприемлемых данных аутентификации и должен сопровождаться WWW-Authenticate. 403 Forbidden означает отказ выполнять понятый запрос. 404 Not Found сообщает об отсутствии ресурса, но сервер также вправе скрыть существование защищенного объекта. Семантику подтверждают RFC 9110 и руководство по аутентификации MDN.

405 Method Not Allowed означает, что сервер знает метод, но целевой ресурс его не поддерживает. Ответ должен содержать Allow со списком доступных методов. Требование приводят RFC 9110 и справка MDN.

409 Conflict подходит для конфликта с текущим состоянием приложения. 412 Precondition Failed точнее описывает провал условия If-Match или If-Unmodified-Since. 415 указывает на неподдерживаемый медиатип. 422 Unprocessable Content подходит, когда формат и синтаксис понятны, но инструкции нельзя выполнить по смыслу. Различия фиксируют RFC 9110 и справки 412 и 422.

429 Too Many Requests сообщает о превышении лимита. Сервер может добавить Retry-After. Такое же поле часто используют с 503 Service Unavailable. Определения подтверждают RFC 6585 и справка MDN.

500 Internal Server Error обозначает непредвиденный сбой приложения. 502 Bad Gateway означает, что шлюз получил неприемлемый ответ от следующего узла. 503 Service Unavailable сообщает о временной недоступности. 504 Gateway Timeout означает, что посредник не дождался следующего сервера.

Не все числа в журналах входят в стандарт HTTP. Например, nginx использует 499, когда клиент закрывает соединение до завершения ответа. Код отсутствует в реестре IANA. Определение приводят материалы nginx и документация Cloudflare.

В реестре IANA также присутствует временный код 104 Upload Resumption Supported. Регистрация действует до 13 ноября 2026 года и относится к незавершенному протоколу возобновляемых загрузок. Использовать код как стабильную часть публичного API пока рискованно. Статус показывают реестр IANA и рабочий документ IETF.

Для первичной диагностики удобно использовать curl. Ключ -i выводит поля ответа вместе с содержимым, а -v показывает детали соединения, отправленные поля и полученный ответ. Поведение описывают документация curl и книга Everything curl.

curl -v https://example.com/api/status
 
 curl -i https://example.com/api/orders 
   -X POST 
   -H "Content-Type: application/json" 
   -H "Accept: application/json" 
   --data '{"product_id":137,"quantity":2}'

Проверять нужно не только итоговый код. Полезно установить фактический URL после перенаправлений, метод, версию HTTP, Content-Type, тело, правила кеширования и узел, который сформировал ошибку. Ответ 502 от CDN и 500 от приложения указывают на разные участки цепочки.

Для ошибок API не нужно изобретать собственный формат без причины. RFC 9457 определяет application/problem+json с полями type, title, status, detail и instance. Реестр формата ведет IANA. Внешний ответ не должен содержать трассировки стека, SQL-запросы, секреты и внутренние пути. Риск утечки подтверждают рекомендации OWASP.

HTTP/1.1 422 Unprocessable Content
 Content-Type: application/problem+json
 
 {
   "type": "https://example.com/problems/invalid-quantity",
   "title": "Некорректное количество",
   "status": 422,
   "detail": "Количество должно быть больше нуля",
   "instance": "/api/orders/requests/7f42"
 }

Частые вопросы

Чем HTTP-запрос отличается от URL?

URL идентифицирует ресурс. HTTP-запрос дополнительно содержит метод, поля и иногда тело. Один адрес можно вызвать разными методами и получить разные результаты.

Можно ли отправить тело в GET-запросе?

HTTP не задает общей семантики для содержимого GET. Сервер или посредник может отклонить либо проигнорировать данные. Для совместимого API лучше использовать строку запроса, POST или QUERY при подтвержденной поддержке.

Чем PUT отличается от PATCH?

PUT создает или заменяет состояние ресурса по известному адресу и считается идемпотентным. PATCH применяет частичное изменение, идемпотентность которого зависит от формата и логики операции.

Почему сервер возвращает 415 при отправке JSON?

Клиент мог не передать Content-Type: application/json, указать неподдерживаемый медиатип или отправить формат, который конечная точка не принимает.

Чем 401 отличается от 403?

401 сообщает об отсутствии подходящих данных аутентификации и сопровождается WWW-Authenticate. 403 означает, что сервер понял запрос, но отказывается его выполнять.

Когда применять 409, а когда 412?

409 подходит для конфликта с бизнес-состоянием ресурса. 412 используют, когда не выполнилось HTTP-условие, например значение If-Match не совпало с текущим ETag.

Есть ли строка статуса в HTTP/2 и HTTP/3?

Текстовой строки вида HTTP/1.1 200 OK нет. Числовой код передается через псевдозаголовок :status, а поясняющая фраза по сети не отправляется.

HTTP проще разбирать, когда каждая часть сообщения выполняет свою роль. Метод задает смысл операции, URI выбирает ресурс, поля описывают условия обмена, тело переносит данные, а код состояния сообщает общий результат. При проектировании API сначала проверьте семантику метода и кода, затем формат содержимого, условные запросы, повторные попытки и поведение прокси. Такой порядок снижает риск ошибок, которые незаметны в локальном тесте, но проявляются после подключения CDN, балансировщика или кеша.

HTTP запрос ответ метод заголовок статус протокол
Alt text
Обращаем внимание, что все материалы в этом блоге представляют личное мнение их авторов. Редакция SecurityLab.ru не несет ответственности за точность, полноту и достоверность опубликованных данных. Вся информация предоставлена «как есть» и может не соответствовать официальной позиции компании.
10 000 человек уже думают как хакеры
Ты — пока нет. Реальные атаки, реальные стенды, реальная разница между «знаю» и «умею».
Присоединиться →
WHITE HAT // verified
РЕКЛАМА

Гиганяшка

Технологии без шума вентиляторов и сухих спецификаций.