Skip to content

Latest commit

 

History

History
2106 lines (1398 loc) · 138 KB

http_11.md

File metadata and controls

2106 lines (1398 loc) · 138 KB

HTTP 1.1

В данной статье речь пойдет о наиболее часто встречающейся (на данный момент) версии протокола: HTTP/1.1.

В разборе протокола и его возможностей одна из важнейших составляющих - это чтение RFC, «Request for Comments».

Это документ из серии пронумерованных информационных документов Интернета, содержащих технические спецификации и стандарты, широко применяемые во всемирной сети. По сути это набор документов о том, что и как работает в Интернете. Так как HTTP является частью работы Интернета, то разработка, становление и применение протокола есть в rfc2616, а также во многих других документах, где протокол расширялся и модифицировался.

Введение

Аббревиатура HTTP расшифровывается как HyperText Transfer Protocol, «протокол передачи гипертекста».

Что такое гипертекст? Обратимся к Wikipedia:

Гиперте́кст (от греч. hyper – сверх) — это вид текста, существующий только в электронном виде. Его основным отличием от обычного текста является наличие гиперссылок (электронных ссылок), которые позволяют по одному щелчку переходить на другие электронные документы.

До появления электронных ссылок гипертекста не существовало.

По сути, наши веб-странички и есть этот самый гипертекст:

Типичная веб-страница представляет собой текстовый файл в формате HTML, который может содержать ссылки на файлы в других форматах (текст, графические > изображения, видео, аудио, мультимедиа, апплеты, прикладные программы, базы данных, веб-службы и прочее), а также гиперссылки для быстрого перехода на > другие веб-страницы или доступа к ссылочным файлам.

Отсюда же и расшифровка аббревиатуры HTML:

HTML (от англ. HyperText Markup Language — «язык гипертекстовой разметки») — стандартизированный язык гипертекстовой разметки документов для просмотра веб-страниц в браузере. Веб-браузеры получают HTML документ от сервера по протоколам HTTP/HTTPS или открывают с локального диска, далее интерпретируют код в интерфейс, который будет отображаться на экране монитора.

Т.е. изначально протокол предназначался и разрабатывался для передачи гипертекстовых документов, однако в настоящий момент используется для передачи произвольных данных (видео, аудио, текст).

Hаботает поверх TCP/TLS по принципу запрос-ответ, т.е. клиентское приложение формирует запрос и отправляет его на сервер, где данный запрос обрабатывается, формирует ответ и отправляется клиенту.

Протокол HTTP является stateless протоколом, т.е. общение с сервером состоит из независимых друг от друга пар запрос/ответ. Сервер может не хранить никакой информации о клиенте, его статусе и т.д.

Пример работы HTTP 1.1

В модели OSI HTTP является протоколом прикладного уровня, уровня приложения, он отвечает за данные. Сама же задача о передаче данных (например, установка соединения и т.д.) возлагается на нижние уровни.

OSI

Протокол HTTP 1.1 обычно использует TCP/IP соединения:

HTTP communication usually takes place over TCP/IP connections. The default port is TCP 80 [19], but other ports can be used. This does not preclude HTTP from being implemented on top of any other protocol on the Internet, or on other networks. HTTP only presumes a reliable transport; any protocol that provides such guarantees can be used; the mapping of the HTTP/1.1 request and response structures onto the transport data units of the protocol in question is outside the scope of this specification.

Однако любой другой надёжный транспортный протокол теоретически может быть использован для доставки HTTP сообщений.

Итак, мы имеем дело с текстовым протоколом прикладного уровня, который является stateless и предназначен для передачи данных по сети.

Как отправлять запросы

Для практики нам понадобится уметь отправлять запросы и принимать ответы, а также тестовые ресурсы.

В этой статье я использовал nc для подключения к серверам и отправки HTTP-запросов, например:

nc -vc stallman.org 80
Connection to stallman.org port 80 [tcp/http] succeeded!

Мы открываем TCP-соединение с stallman.org по 80-порту, т.е. создали подключение с сервером. После чего можем писать запросы.

Можно также использовать telnet, если он у вас есть:

telnet stallman.org 80

Подойдет любой http-клиент: curl, postman, nc, telnet и т.д.

httpbin.org

Для тестового стенда, куда можно будет отправлять запросы, можно использовать httpbin.org.

Этот ресурс свободно доступен и предоставляет интерфейс, чтобы отправлять различные запросы и эксперементировать, в случае, если вы хотите ознакомиться с HTTP и не хотите работать с консолью.

При этом описываются запросы, которые вы отправляете, ответы, которые получаете. К httpbin.org также можно слать запросы и через nc или telnet.

В некоторых примерах я буду слать запросы на stallman.org, хотя в принципе подойдет любой ресурс.

Структура сообщения HTTP/1.1

Сначала разберем из чего состоят HTTP-запросы, отправим такой запрос и посмотрим на то, что из этого вышло.

Запрос HTTP

Каждый HTTP-запрос состоит из трёх частей, которые передаются в указанном порядке: строка запроса (request line), заголовки (headers) и тело сообщения (body).

http request

Request line

Строка запроса представляет из себя запись в виде: <Method> <Path> <HTTP/Version>.

Метод

Метод (Method) - это тип запроса, одно слово заглавными буквами. Чаще всего это глагол, как в нашем примере, но может быть и существительным.

Список методов, предоставляемых протоколом, будет разобран позже, ну а пока достаточно просто понимать, что метод - это по сути некоторое действие, которое мы хотим сделать с помощью запроса. В нашем случае - это получить (GET) ресурс.

Путь

Путь (Path) - это путь к запрашиваемому ресурсу, Request-URI.

Понятно, что когда делается запрос до какого-либо ресурса нужен путь до него, идентификатор ресурса. Просто, чтобы понимать к какому ресурсу идет обращение.

Это и есть URI, Uniform Resource Identifier: унифицированный (единообразный) идентификатор ресурса. URI — это строка символов, которая используется для идентификации какого-либо ресурса по его адресу (URL) или по его имени (URN), либо по тому и тому вместе.

Т.е. URI - это идентификатор ресурса, но не сказано какой конкретно идентификатор. А URL, т.е. Uniform Resource Locator - это уже уточнение, более конкретная информация, это идентификатор выражающий местоположение ресурса. В свою очередь URN, Uniform Resource Name - это тоже уточнение, это идентификатор выражающий имя ресурса (и не важно где его местоположение).

Если мы говорим про веб и интернет, то чаще всего используется URL, так как происходит поиск определенного ресурса именно по его адресу на каком-то сервере. Зачастую, когда говорят URI, подразумевается именно URL. Хотя по факту это не совсем так, потому что URL является частью URI. В контексте веба URN практически не используется, но может быть использовано, например, в Jabber.

Подробнее про разницу

URL принято раскладывать на составляющие:

scheme ":"  hier-part [ "?" query ] [ "#" fragment ]
  1. Схема (scheme) — протокол обращения к ресурсу (часто указывает на сетевой протокол), например http или ftp.

  2. Иерархическая-часть (hier-part) - содержит данные, обычно организованные в иерархической форме, которые служат для идентификации ресурса.

    Обычно содержит путь к ресурсу (и, возможно, перед ним, адрес сервера, на котором тот располагается) или идентификатор ресурса.

  3. Запрос (query или query string) — часть после знака ? до знака # или конца строки.

    Ее принято раскладывать на пары вида ключ=значение, при передаче нескольких пар они связываются через разделитель &.

    Используется в случае, если надо дополнительно передать какие-то параметры через URL.

  4. Фрагмент (fragment, часто встречается под названием якорь, anchor) — это часть после знака #.

    Традиционно рассматривается как адресация внутри запрошенного документа.

Пример абсолютного URI:

https://ru.wikipedia.org/wiki/URI

Пример относительного URI:

/relative/URI/with/absolute/path/to/resource.txt

В примере с изображения HTTP-запрос использовал относительный URI путь /, т.е. корень сайта.

Возможен и такой вариант HTTP-запросов:

GET http://developer.mozilla.org/ru/docs/Web/HTTP/Messages HTTP/1.1

Пример с query string:

GET /test/demo_form.php?name1=value1&name2=value2 HTTP/1.1

Здесь путь до ресурса - это /test/demo_form.php, а query string - это ?name1=value1&name2=value2.

В наших HTTP-запросах (здесь и далее) схема, хост и порт опускаются (и считаются совпадающими с параметрами соединения).

Версия

Версия протокола - это HTTP и пара разделённых точкой цифр. В нашем случае это HTTP/1.1.

Header's

После request line можно указать заголовки сообщения.

Заголовки характеризуют тело сообщения, параметры передачи, сжатия и прочие сведения. Это своего рода метаинформация.

Заголовок - это строка, содержащая не чувствительное к регистру название, а затем после двоеточия непосредственно значение. Пробелы перед значением игнорируются. Заголовки часто указывают заглавными буквами, но регистр здесь не важен. Несколько заголовков отделяются символом перевода строки:

Host: httpbin.org
User-Agent: google сhrome

Каким образом сервер понимает, что мы закончили передавать данные? Это должен быть какой-то маркер. В HTTP это делается с помощью двух переводов строки.

Заголовки - это то, почему HTTP протокол стал настолько гибким и расширяемым, ведь благодаря им можно влиять на кэшируемость, соединение, добавлять функционал и многое другое. Это мощный инструмент, который делает HTTP протокол тем, чем он является сейчас.

Для версии протокола 1.1 в запросе обязательно должен присутствовать заголовок Host. Про это будет буквально через пару минут.

Ну а пока, продолжим.

Тело сообщения

Тело сообщения - это непосредственно данные сообщения. Оно бывает не у всех запросов: запросы, собирающие (fetching) ресурсы, такие как GET, в нем не нуждаются.

Обязательно должно отделяться от заголовков пустой строкой.

Пример запроса

Как уже было сказано, для того, чтобы сформировать HTTP-запрос, необходимо составить стартовую строку, а также задать по крайней мере один заголовок — это заголовок Host, который является обязательным, и должен присутствовать в каждом запросе.

Поключимся к httpbin.org:

nc -v httpbin.org 80
Connection to httpbin.org port 80 [tcp/http] succeeded!

И сделаем запрос:

GET /get HTTP/1.1
Host: httpbin.org

Строка запроса здесь говорит о том, что мы пытаемся получить (GET) ресурс по пути /get, версия протокола HTTP/1.1, без тела сообщения. При этом, указываем, что обращаемся к хосту httpbin.org, через заголовок Host.

В ответ получаем:

HTTP/1.1 200 OK
Date: Fri, 04 Aug 2023 07:45:23 GMT
Content-Type: application/json
Content-Length: 199
Connection: keep-alive
Server: gunicorn/19.9.0
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true

{
  "args": {},
  "headers": {
    "Host": "httpbin.org",
    "X-Amzn-Trace-Id": "Root=1-64ccac91-77e0eb2e121a39fc257488f5"
  },
  "origin": "79.139.164.100",
  "url": "http://httpbin.org/get"
}

Теперь подробнее разберем структуру ответа.

Ответ HTTP

Каждый HTTP-ответ состоит из строки статуса (status line), заголовков (headers) и тела ответа (body).

http response

Status line

Строка статуса представляет из себя запись в виде: <HTTP/Version> <Status Code> <Status Message>.

Версия (HTTP/Version)- это пара разделённых точкой цифр, как и в запросе.

Код состояния (Status Code) - это три цифры. По коду состояния определяется дальнейшее содержимое сообщения и поведение клиента. Это помогает быстро понять был ли, например, запрос успешным или ошибочным, не разбираясь в остальном ответе.

Пояснение (Status Message) - текстовое короткое пояснение к коду ответа для пользователя. Никак не влияет на сообщение и является необязательным.

Header-ы

Имеют ту же структуру, что и заголовки запросов.

Существует множество заголовков ответов, их можно разделить на несколько групп и об этом пойдет речь позже.

Тело ответа

Последней частью ответа является его тело.

У ответа может не быть тела, если код состояния дает необходимую информацию.

Например у ответов с кодом состояния 204 (204 No Content), оно обычно отсутствует.

Как и в запросах, тело ответа отделяется от заголовков пустой строкой.

Пример ответа

На наш предыдущий запрос к httpbin.org:

HTTP/1.1 200 OK
Date: Fri, 04 Aug 2023 07:45:23 GMT
Content-Type: application/json
Content-Length: 199
Connection: keep-alive
Server: gunicorn/19.9.0
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true

{
  "args": {},
  "headers": {
    "Host": "httpbin.org",
    "X-Amzn-Trace-Id": "Root=1-64ccac91-77e0eb2e121a39fc257488f5"
  },
  "origin": "79.139.164.100",
  "url": "http://httpbin.org/get"
}

Обратите внимание, что наш ответ содержит и заголовки, и тело.

Заголовки

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

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

Важное свойство заголовков — это возможность считывать их до того, как получено тело сообщения. Таким образом можно влиять на обработку запроса или ответа, например.

Клиент может добавлять как уже описанные в RFC заголовки, так и собственные. В этом есть и минусы: поскольку придуманные имена заголовков могут случайно совпасть с какими-то из существующих стандартных имён из RFC (или в будущем добавят заголовок, совпадающий по названию с вашим). Поэтому раньше во избежание подобных коллизий использовался префикс X-, однако сейчас этот подход устарел.

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

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

Разберем некоторые из наиболее часто встречающихся заголовков, другие же будут упомянуты при разборе методов, статусов ответов.

Популярные заголовки

Content-Type

Заголовок содержит информацию об исходном типе документа. Говоря про содержание заголовка Content-Type имеют в виду MIME тип документа.

MIME-тип ("media type" или "content type") - это строка, отправляемая вместе с файлом, которая указывает тип файла (например, передаваемый аудиофайл может быть помечен как audio/ogg тип, а изображение - image/png). MIME-тип играет точно такую же роль, как и расширение файла в системе Windows. Когда HTTP-сообщение содержит Content-type заголовок, тело запроса будет парситься в соответствии с MIME-типом, указанным в заголовке.

Пример: Content-Type: application/json

Указывать тип документа необходимо, так как к содержимому запроса могут быть применены различные операции, например, сжатие. Поэтому надо понимать исходный тип документа.

Список MIME типов

Content-Length

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

Пример: Content-Length: 1024

Content-Encoding

Заголовок представляет собой упорядоченный список всех кодировок (например, сжатия), примененных к сообщению. Это позволяет клиенту декодировать представление, возвращая ресурс в исходное состояние (это еще раз подчеркивает важность Content-Type). Типичным примером этого является сжатие. Время передачи документа сокращается, и клиент (благодаря наличию информации о том, что было за сжатие) может воссоздать исходный носитель после его поступления.

Пример: Content-Encoding: deflate, br

Host

Представьте, что у вас есть сайт. Он расположен на неком сервере (это еще называют хостингом).

Когда пользователь вводит доменное имя (адрес вашего сайта) в браузер происходит преобразование доменного имени ("www.mysite.ru") в IP-адрес, после чего открывается TCP-соединение. Выделять на каждый маленький сайт и ресурс целый сервер расточительно. Было бы гораздо лучше, если бы существовал механизм, при котором множество веб-сайтов было бы расположено на одном веб-сервере!

Посетители веб-сайта направляются по имени хоста или IP-адресу на правильный виртуальный хост. Виртуальный хостинг позволяет компаниям, использующим один сервер, иметь свои собственные доменные имена. Например, "www.company1.com" и "www.company2.com" могут размещаться на одном сервере.

Это и называется виртуальный хостинг.

Virtual Hosting

Заголовок запроса Host указывает доменное имя и порт хоста запрашиваемого ресурса. Необходимо для поддержки виртуального хостинга на серверах.

Если порт не указан, предполагается, что он равен 80 для соединения HTTP или порт 443 для соединения HTTPS.

Этот заголовок является обязательным в запросах HTTP/1.1. Если сервер получает HTTP-запрос, который не включает этот HTTP-заголовок, он вернет статус HTTP 400 Bad Request.

Cache-Control

Заголовок HTTP Cache-Control используется как для HTTP-запросов, так и для HTTP-ответов, служит для управления (с помощью директив) кэшем в клиентских браузерах и промежуточных сервисах, таких как прокси-серверы и CDN.

CDN (Content Delivery Network) — это географически распределённая сетевая инфраструктура, обеспечивающая быструю доставку контента пользователям веб-сервисов и сайтов. Входящие в состав CDN cерверы географически располагаются таким образом, чтобы сделать время ответа для пользователей сайта/сервиса минимальным.

Грубо говоря, это сервера, которые кэшируют контент сайтов (например, картинки) и отдают пользователю по запросу. Сервера эти располагаются по всему миру, таким образом данные клиент может забирать не с основного сервера (который может располагаться вообще хоть где), а сервера, который близко географически и таким образом увеличить скорость загрузки.

CDN

Примеры заголовков:

Cache-Control: no-cache
Cache-Control: no-store
Cache-Control: max-age=3600
Cache-Control: max-stale=0
Cache-Control: min-fresh=0
Cache-Control: no-transform
Cache-Control: only-if-cached
Cache-Control: cache-extension

Настройка кэширования выходит за рамки статьи, поэтому об этом лучше прочитать отдельно.

User-Agent

Заголовок отправляется клиентом, чтобы сообщить серверу, что за пользовательский агент шлет запрос. Пользовательским агентом может быть как браузер, так и поисковая система (которая занимается индексацией веб-сайтов).

Веб-сайты для мобильных телефонов часто вынуждены полагаться на определение User-Agent, так как браузеры на мобильных телефонах имеют серьезные различия. Поэтому обычно разным устройствам отдаются разные страницы в зависимости от модели мобильного телефона. Эти различия могут быть как небольшими (изменение размера изображений специально для меньших экранов), так и весьма существенными.

User-Agent: Mozilla/5.0 (X11; Linux i686; rv:2.0.1) Gecko/20100101 Firefox/4.0.1

Cookie

Как уже сказано было в начале: общение с сервером состоит из независимых друг от друга пар запрос/ответ. Сервер не хранит никакой информации о клиенте, его статусе и т.д. Каждый запрос для сервера как новый, он не может отличить один от другого (это запрос от пользователя, который уже был на сайте или новый?).

Однако, сервер должен понимать, что за пользователь пришел, чтобы, например, пользователь не логинился каждый раз заново. Вот для этого и служит заголовок Cookie - это передача состояния (например, сессии) на сервер или от сервера.

Т.е. это небольшой фрагмент данных, отправленный веб-сервером и хранимый на компьютере пользователя. Клиент (например, браузер) всякий раз при попытке открыть страницу соответствующего сайта пересылает этот фрагмент данных серверу в составе запроса. В куках может хранится не только информация о аутентификации, а еще и, к примеру, хранения персональных предпочтений и настроек пользователя или хранения сведений статистики о пользователях (помните все эти выпадающие плашки на сайтах, где вас просят разрешить использование кук?).

С сервера cookie передаются посредством заголовка ответа HTTP Set-Cookie:

HTTP/1.1 200 OK
Content-Type: text/html
Set-Cookie: items=16
Set-Cookie: headercolor=blue
Set-Cookie: footercolor=green
Set-Cookie: screenmode=dark, Expires=Sun, 1 Jan 2023 12:00:00 GMT
Set-Cookie: job=111; Max-Age: 3600; Secure; HttpOnly

При этом где хранить куки уже решает клиент (например, браузер). В том числе можно устанавливать время хранения, обратите внимание на Set-Cookie: screenmode=dark, Expires=Sun, 1 Jan 2023 12:00:00 GMT и значение Expires.

Запрос с уже установленными куками:

GET / HTTP/1.1
Host: www.example.re
Cookie: items=16; headercolor=blue; screenmode=dark; job=111

Имена кук нечувствительны к регистру.

Помните, что куки - это не игрушка, многие браузеры имеют ограничение на размер хранимых данных там, так и на количество хранимых кук.

Также, у них есть и серьезные недостатки, поэтому хранить там, например, пароль пользователя не надо.

Authorization

Заголовок авторизации, который используется для предоставления данных пользователя (например, токена авторизации), разрешающих клиенту взаимодействовать с защищенным ресурсом.

GET /resource HTTP/1.1
Host: server.example.com
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQSflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c

Connection

Заголовок используется для управления соединением. Существуют две директивы: keep-alive и close.

Директива keep-alive указывает, что клиент хочет, чтобы соединение сохранялось и оставалось открытым после завершения текущего запроса. Это настройка по умолчанию для версии HTTP/1.1.

В версии HTTP 1.0 соединение закрывалось сразу после обработки запроса, т.е. на каждый запрос устанавливалось новое соединение.

В HTTP 1.1 соединение будет закрыто, если:

  1. Сервер или клиент использует версию HTTP младше 1.1
  2. Сервер или клиент передал заголовок Connection: close
  3. По истечению таймаута

Etag

Заголовок ETag ("тега объекта") — это идентификатор, предназначенный для уникальной идентификации конкретной версии ресурса. Например, более поздним версиям документов по тому же URL-адресу будут присвоены новые значения ETag.

ETag используется, чтобы указать, доступны ли новые или разные версии одного и того же ресурса. Это позволяет клиентам экономить траффик за счет кэширования на стороне клиента, не загружая повторно версии уже имеющихся ресурсов.

Теперь пришла пора более подробно поговорить о методах HTTP запросов.

Методы

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

Являются частью Request line. Относятся только к запросам.

Для методов в HTTP определены свойства безопасности, идемпотентности и кэшируемости.

Безопасность (Safe)

Метод HTTP является безопасным, если он не меняет состояние сервера. Другими словами, безопасный метод проводит операции "только чтение" (read-only).

Пример безопасного метода: GET.

Идемпотентность (Idempotent)

Methods may also have the property of "idempotence" in that (aside from error or expiration issues) the side-effects of N > 0 identical requests is the same as for a single request.

The methods GET, HEAD, PUT and DELETE share this property.

Метод HTTP является идемпотентным, если повторный идентичный запрос, сделанный один или несколько раз подряд, имеет один и тот же эффект, не изменяющий состояние сервера.

Для идемпотентности нужно рассматривать только изменение фактического внутреннего состояния сервера, а возвращаемые запросами коды статуса могут отличаться: первый вызов DELETE (появился в HTTP 1.1, отвечает за удаление ресурса) вернёт код 200, в то время как последующие вызовы вернут код 404. При этом DELETE будет идемпотентным.

Кэшируемость

Ответы на некоторые методы могут быть закэшированы. Кэшируемые ответы - это HTTP ответы, которые могут быть сохранены для дальнейшего переиспользования, тем самым снижая число запросов к серверу. Не все HTTP-ответы могут быть закэшированы.

http cache

При этом применять кэширование можно на разных этапах: как ближе к клиенту (на прокси, например), так и ближе к серверу (на gateway-е).

В кэшах могут быть изоображения, статические данные.

Прокси также может выполнять не только задачи кэширования: может быть реализована логика по фильтрации (сайтов, слов), аутентификация и т.д.

HTTP методы

GET

Получение указанного ресурса/документа.

GET /get HTTP/1.1
Host: httpbin.org

Обладает свойствами безопасности, кэшируемости и идемпотентности.

Важно понимать, что это не значит, что все GET запросы будут кэшироваться, это означает, что они могут быть закэшированы.

Чисто теоретически, он, как и любой запрос в HTTP, может иметь тело, но это строго не рекомендуется.

A payload within a GET request message has no defined semantics; sending a payload body on a GET request might cause some existing implementations to reject the request.

Необходимые же параметры должны быть переданы либо в URI запроса, либо в заголовках.

The GET method means retrieve whatever information ([...]) is identified by the Request-URI.

Соответственно, GET-запросы зачастую в строке запроса (request line) содержат еще параметры запроса (request parameters), передающиеся в query string:

GET /search.jsp?q=hello&range=ALL&interval=ALL&user=&_usertopic=on HTTP/1.1
Host: www.linux.org.ru

Сам запрос был ресурсу www.linux.org.ru/search.jsp, а в query string были переданы параметры q=hello, range=ALL, interval=ALL, user= и _usertopic=on.

Условный и Частичный

В некоторых ситуациях возникает потребность запросить ресурс через GET, но при некотором условии, например, если он был изменен. Для этого добавляются специальные заголовки: If-Modified-Since, If-Match, If-Range и подобные.

В таком случае применяется так называемый conditional get:

The semantics of the GET method change to a "conditional GET" if the request message includes an If-Modified-Since, If-Unmodified-Since, If-Match, If-None-Match, or If-Range header field.

Применяется для того, чтобы сократить количество запросов, более гибко управлять закэшированными ресурсами:

A conditional GET method requests that the entity be transferred only under the circumstances described by the conditional header field(s). The conditional GET method is intended to reduce unnecessary network usage by allowing cached entities to be refreshed without requiring multiple requests or transferring data already held by the client.

Кроме conditional GET, различают ещё partial GET - частичный запрос, получающий часть ресурса. В частичный запрос добавляется заголовок Range.

The semantics of the GET method change to a "partial GET" if the request message includes a Range header field. A partial GET requests that only part of the entity be transferred.

Так как в HTTP мы оперируем байтами, то благодаря заголовкам, возможно запросить какую-то часть ресурса (в байтовом представлении). Т.е. получить не все содержимое ресурса, а только его фрагмент. Для этого в заголовках указываются байтовые диапазоны фрагмента.

Стоит отметить, что если сервер не поддерживает работу с частичными запросами, то будет возвращен весь ресурс, а заголовки Range будут проигнорированы.

Частичные GET в основном используются для докачки файлов и быстрого параллельного скачивания в нескольких потоках. Некоторые программы скачивают заголовок архива, выводят пользователю внутреннюю структуру, а потом уже запрашивают фрагменты с указанными элементами архива.

HEAD

Аналогичен методу GET, за исключением того, что в ответе сервера отсутствует тело. Применяется для извлечения метаданных (заголовки), проверки наличия ресурса (валидация URL) и чтобы узнать, не изменился ли он с момента последнего обращения.

HEAD /index.html

Обладает свойствами безопасности, кэшируемости и идемпотентности.

POST

Предназначен для отправки данных на сервер, передачи пользовательских данных заданному ресурсу.

Данные могут быть произвольными. Тип тела сообщения указывается в заголовке Content-Type. Размер тела сообщения передается в заголовке Content-Length и измеряется в байтах.

Пример с формой (обратите внимание на заголовки):

POST /test HTTP/1.1
Host: foo.example
Content-Type: application/x-www-form-urlencoded
Content-Length: 27

field1=value1&field2=value2

Можно также посмотреть пример с формой тут.

А вот пример запроса с телом в формате json:

POST /echo/post/json HTTP/1.1
Host: reqbin.com
Accept: application/json
Content-Type: application/json
Content-Length: 81
      
{
  "Id": 78912,
  "Customer": "Jason Sweet",
  "Quantity": 1,
  "Price": 18.00
}

Не обладает свойствами безопасности, кэшируемости и идемпотентности.

PUT

Применяется для загрузки содержимого запроса на указанный в запросе URI. Создаёт новый ресурс или заменяет представление целевого ресурса, данными представленными в теле запроса.

The PUT method requests that the enclosed entity be stored under the supplied Request-URI.

PUT /questions/{question-id}

Не обладает свойствами безопасности, кэшируемости.

POST vs PUT

Фундаментальное различие методов POST и PUT заключается в следующем: POST предполагает, что по указанному URI будет производиться обработка передаваемого клиентом содержимого.

Используя PUT, клиент предполагает, что загружаемое содержимое соответствует находящемуся по данному URI ресурсу. Если ресурса по данному URI не существует, то он должен быть создан.

По сути предполагается, что PUT содержит в URI идентификатор ресурса, в то время как POST будет обрабатывать каждый запрос как новый и не обязан содержать никакие идентификаторы.

Отсюда следует и то, что PUT является идемпотентентным. Представьте, что вы дважды вызывали загрузку:

PUT /questions/id1
PUT /questions/id1
PUT /questions/id1

Идентификатор один и тот же, а значит повторные вызовы не приведут к созданию трех сущностей.

Обычно POST используется для создания сущностей, а PUT для полного обновления (замены) уже существующих.

PUT POST
Ожидается идентификатор ресурса, если ресурса по заданному URI нет, то его необходимо создать Каждый запрос обрабатывается как новая сущность
Идемпотентный Не идемпотентный
Может быть использован, когда необходимо заменить отдельный ресурс, который уже является частью коллекции ресурсов. Полностю заменяет ресурс Может быть использован, когда надо добавить новый ресурс
Не должен кэшироваться Не должен кэшироваться, но может, если будут явные заголовки Cache-Control или Expires
Обычно используется для обновления/замены ресурса Обычно используется для создания ресурса

PATCH

Аналогично PUT, но применяется только к фрагменту ресурса, т.е. частично изменяет ресурс.

PATCH /my/data HTTP/1.1
Host: example.org
Content-Length: 326
Content-Type: application/json-patch+json
If-Match: "abc123"

[
  {
    "op":"test",
    "path":"/a/b/c",
    "value":"foo"
  },
  {
    "op":"remove",
    "path":"/a/b/c"
  },
  {
    "op":"add",
    "path":"/a/b/c",
    "value":[
      "foo",
      "bar"
    ]
  },
  {
    "op":"replace",
    "path":"/a/b/c",
    "value":42
  },
  {
    "op":"move",
    "from":"/a/b/c",
    "path":"/a/b/d"
  },
  {
    "op":"copy",
    "from":"/a/b/d",
    "path":"/a/b/e"
  }
]

Не обладает свойствами безопасности, кэшируемости.

Может как быть идемпотентным, так и не быть, в отличие от PUT, который всегда идемпотентен.

Например, если автоинкрементное поле является частью ресурса, то PUT перезапишет его (т.к. он перезаписывает всё), а PATCH может и не перезаписать.

PATCH vs PUT

Разница между этими методами заключается в том, что PATCH применяется для частичного обновления (partial update) сущности, ресурса. И применяется только к одной сущности, идентификатор которой должен быть передан.

В то время как PUT заменяет или создает (если ее не было) сущность.

Метод PATCH может как быть идемпотентным, так и не быть. Однако из-за того, что он меняет ресурс, а не заменяет, то обычно пишут, что он не идемпотентный.

PUT PATCH
Ожидается идентификатор ресурса, если ресурса по заданному URI нет, то его необходимо создать Ожидается идентификатор ресурса, если ресурса по заданному URI нет, то трактовать как ошибку запроса
Идемпотентный Не идемпотентный
Для полной замены ресурса Для частичного обновления ресурса
Не должен кэшироваться Не должен кэшироваться

DELETE

Удаляет указанный ресурс.

DELETE /file.html HTTP/1.1

Является идемпотентным.

Не обладает свойствами безопасности, кэшируемости.

Может иметь тело как в ответе, так и в запросе.

OPTIONS

Используется для определения возможностей веб-сервера или параметров соединения для конкретного ресурса. В запросе можно указать URL ресурса или * (звёздочку) чтобы указать весь сервер целиком.

OPTIONS /index.html HTTP/1.1
OPTIONS * HTTP/1.1

Для примера продемонстрируем и запрос, и ответ:

 nc -v example.org 80
Connection to example.org port 80 [tcp/http] succeeded!
OPTIONS * HTTP/1.1
Host: example.org

HTTP/1.1 200 OK
Allow: OPTIONS, GET, HEAD, POST
Content-Type: text/html; charset=UTF-8
Date: Fri, 04 Aug 2023 13:14:26 GMT
Server: ECS (nyb/1D1F)
Content-Length: 0

Является идемпотентным и безопасным, но не обладает свойствами кэшируемости.

Запросы OPTIONS * HTTP/1.1 можно применять для проверки доступности сервера, как аналог пинга, тестирования на предмет поддержки сервером протокола HTTP 1.1.

При этом надо понимать, что между OPTIONS и HEAD большая разница.

У этих запросов разное назначение:

  1. HEAD служит для проверки существования ресурса, он полностью аналогичен GET, но без тела ответа.
  2. OPTIONS служит для получения параметров для ресурса или для сервера в целом и при этом сам ресурс никак не затрагивается.

TRACE

Выполняет проверку обратной связи по пути к целевому ресурсу, предоставляя полезный механизм отладки.

Конечный получатель запроса должен отразить полученное сообщение, исключая некоторые поля описанные ниже, назад клиенту как тело сообщения с ответом 200 (OK) с заголовком Content-Type: message/http. Таким образом можно посмотреть что происходит с сообщением на промежуточных узлах.

Конечный получатель - это либо исходный сервер, либо первый сервер получивший значение Max-Forwards в запросе.

Является идемпотентным, но не обладает свойствами кэшируемости и безопасности.

CONNECT

Запускает двустороннюю связь с запрошенным ресурсом. Метод можно использовать для открытия туннеля. Обычно чтобы содействовать установлению защищённого SSL-соединения через нешифрованный прокси.

This specification reserves the method name CONNECT for use with a proxy that can dynamically switch to being a tunnel (e.g. SSL tunneling)

Не обладает свойствами идемпотентности, кэшируемости и безопасности.

Сводная таблица наиболее популярных методов:

Метод Идемпотентный Безопасный Кэшируемый
GET Да Да Да
HEAD Да Да Да
POST Нет Нет Иногда
PUT Да Нет Нет
PATCH Нет Нет Нет
DELETE Да Нет Нет

HTTP коды ответа

Код состояния является частью первой строки ответа сервера, по нему клиент может понять результат его запроса и определить что делать дальше.

Код ответа представляет собой целое число из трёх цифр, где первое число указывает на класс (группу), к которой относится код. Всего выделяют пять групп:

  1. 1xx - Informational, информационные
  2. 2xx - Success, упешное выполнение
  3. 3xx - Redirection, перенаправление
  4. 4xx - Client Error, ошибка на стороне клиента
  5. 5xxx - Server Error, ошибка на стороне сервера

Далее рассмотрим коды по группам и когда их можно ожидать в ответах на запросы. Обратите внимание на то, что важную роль играют и заголовки.

ВАЖНО: Здесь будут рассмотрены статусы именно из протокола HTTP 1.1. В более новых версиях (например, HTTP 2.0) были добавлены новые статусы (например, 421 Misdirected Request), о которых речи в данной статье не будет. Также не будут рассматриваться статусы, которые были введены вместе с WebDAV, протоколом, расширяющим HTTP.

1xx Informational

Класс информационных кодов. Для координации действий клиента и веб-сервера. При работе с версией HTTP 1.0 сообщения с такими кодами должны игнорироваться.

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

Примеры: 100 Continue

100 Continue

Код состояния 100 говорит о том, что клиент может (должен) продолжать запрос. Сервер должен отправить окончательный ответ после завершения запроса.

Целью статуса 100 является разрешить клиенту, который отправляет сообщение запроса с телом запроса чтобы определить, готов ли исходный сервер принять запрос (на основе заголовков запроса) до того, как клиент отправит запрос тело. В некоторых случаях это может быть крайне неэффективно для клиента отправлять тело, если сервер отклонит сообщение.

Для того, чтобы сообщить серверу, что данный запрос является проверочным, на который клиент ждет либо разрешение на отправку запроса с телом, либо запрет, используется заголовок Expect: 100-continue.

Пример использования: отсылаем большой pdf файл, но сначала хотим убедиться, что сервер готов принять такой запрос. Спрашиваем его о готовности с помощью заголовка Expect: 100-continue, при этом сообщаем, что в теле будет Content-Type: application/pdf, т.е. pdf документ размером Content-Length: 99000:

PUT /docs HTTP/1.1
Host: www.example.re
Content-Type: application/pdf
Content-Length: 99000
Expect: 100-continue

Ответ от сервера, что он готов принять запрос с таким pdf-документом:

HTTP/1.1 100 Continue

Отсылаем уже запрос вместе с телом:

<PDF file contents are sent as message body>

И конечный ответ от сервера:

HTTP/1.1 200 OK

101 Switching Protocols

Статус говорит о том, что сервер выполняет требование клиента, текущая сессия может быть продолжена и переключает (если это возможно) протокол на тот, который указал клиент. Для того, чтобы указать, что клиент просит переключить протокол и на какой протокол переключать в запросе должны присутствовать заголовки:

Connection: upgrade
Upgrade: protocol-name[/protocol-version]

Поддерживается также возможность указать несколько протоколов через запятую.

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

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

Важно понимать, что поле заголовка Upgrade применяется только к переключению протокола прикладного уровня.

Поле заголовка Upgrade применяется только к непосредственному соединению, следовательно, ключевое слово upgrade должно быть указано у соединения, используя заголовок Connection.

Для наглядности пример:

Запрос:

GET /index.html HTTP/1.1
Host: www.example.re
Connection: upgrade
Upgrade: HTTP/3, HTTP/2

Ответ:

HTTP/1.1 101 Switching Protocols
Upgrade: HTTP/2
Connection: upgrade

102 Processing

Является устаревшим и не входящим в современную спецификацию HTTP 1.1, однако можно встретить применение этого статус кода (например, при работе с серверами, работающими по более старой спецификации HTTP 1.1).

Сервер может ответить клиенту статус 102 Processing, тем самым сообщая, что запрос принят, но его выполнение требует длительного времени, поэтому клиент не должен обрывать соединение из-за превышения времени ожидания (таймауту). Клиент при получении такого ответа должен сбросить таймер ожидания и дожидаться следующей команды в обычном режиме.

103 Early Hints

Является экспериментальным:

This document is not an Internet Standards Track specification; it is published for examination, experimental implementation, and evaluation.

Используется для раннего возврата части заголовков.

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

Т.е. когда сервер может сказать клиенту (браузеру), что вот эти css stylesheets или скрипты понадобятся для дальнейшей работы и их лучше было бы заранее подгрузить. Для указания что именно подгружать используются заголовки Link:

HTTP/1.1 103 Early Hints
Link: </style.css>; rel=preload; as=style
Link: </script.js>; rel=preload; as=script

// wait a few hundred milliseconds

HTTP/1.1 200 OK
Date: Fri, 26 May 2017 10:02:11 GMT
Content-Length: 1234
Content-Type: text/html; charset=utf-8
Link: </style.css>; rel=preload; as=style
Link: </script.js>; rel=preload; as=script

2xx Success

Коды из этого класса говорят клиенту, что его запрос был получен и обработан успешно.

200 OK

Статус код 200 ОК говорит о том, что был произведен успешный запрос. Если клиентом были запрошены какие-либо данные, то они находятся в заголовке и/или теле сообщения.

Ответы с кодом 200 почти всегда имеют тело, в котором хранятся данные о результате запроса. Что это за данные могут быть? Зависит от запроса и метода запроса. Это может быть идентификатор, статус выполнения задачи/запроса или ресурс целиком.

GET-запрос

При таком запросе в теле ответа ожидается сущность или ресурс, который мы запрашиваем:

Запрос:

GET /hello-world.txt HTTP/1.1
Accept: text/*

Ответ:

HTTP/1.1 200 OK
Content-Type: text/markdown
Content-Length: 778

[200 OK][1] is the most common HTTP status code. It generally means that the
HTTP request succeeded.
POST-запрос

Информация о статусе или результате выполнения запроса.

Например, вы добавляете новую задачу в таск-трекер и в таком случае можно вернуть ее уникальный идентификатор в таск-трекере:

HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 45

{"id":"42d08e06-35fb-11ee-be56-0242ac120002"}
PUT/DELETE-запрос

В случае PUT или DELETE в теле ответа возвращается информация о статусе запроса:

HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 19

{"deleted":"true"}

201 CREATED

Статус код 201 CREATED говорит о том, что был произведен успешный запрос и некоторый ресурс (сущность) были успешно созданы.

Запрос:

POST /incoming/xml HTTP/1.1
Host: www.example.re
Content-Type: application/xml
Content-Length: 104
<?xml version="1.0">
<article>
  <title>Test XML article</title>
  <author>Anonymous</author>
</article>

Ответ:

HTTP/1.1 201 Created
Location: /incoming/xml/article_1.xml
Content-Type: application/json
Content-Length: 19

{"success":"true"}

На мой взгляд, возвращать 201 на создание ресурса (той же задачи в таск-трекере) более идиоматично, нежели возвращать 200. Хотя встречаются и такие, и такие реализации.

Разница с 200 OK в том, что 201 CREATED порождает новую сущность, т.е. мы создаем ресурс, в то время как 200 OK вполне может не являться ответом на создание чего-либо.

202 ACCEPTED

Код ответа говорит о том, что запрос принят, но его обработка не завершена и сервер не гарантирует, что она завершится успешно.

Например, клиент отправляет запрос на запуск и обработку некоего процесса, гарантировать, что процесс отработает успешно на момент запуска мы не можем: представьте себе сложный процесс, различные интеграции и прочее. Запрос мы приняли успешно, а по результату работы нашего сложного процесса мы, например, хотим отправить пользователю электронное письмо с сообщением о том, что процесс сработал или нет. Либо предоставить другую конечную точку в API, которая может указывать текущее состояние этого процесса.

В таком случае, мы можем клиенту на его запрос вернуть 202 ACCEPTED.

Запрос (опустим тело запроса для простоты):

POST /my-batch-process HTTP/1.1
Content-Type: application/json

...

Ответ:

HTTP/1.1 202 Accepted
Link: </batch-status/5545> rel="http://example.org/batch-status"
Content-Length: 0

В заголовке мы явно укажем где пользователю искать статус задачи/процесса.

203 Non-Authoritative Information

Статус код говорит о том, что запрос успешен, но тело запроса, которое отдал сервер, было изменено прокси-сервисом. Такая ситуация может быть возможна, так как наш запрос, прежде чем дойти до сервера, может пройти еще и через прокси-сервис, стоящий перед сервером. И этот прокси сервис может изменить тело ответа, например:

Запрос:

GET /instructions HTTP/1.1
Host: www.example.re

Ответ от сервера:

HTTP/1.1 200 OK
Content-Type: text/plain; charset=UTF-8
Content-Length: 250

<message body will follow in text format>

Ответ от прокси:

HTTP/1.1 203 Non-Authoritative Information
Content-Type: application/json
Content-Length: 265

{"response":"<message body will be embedded in this JSON object>"}

Код 203 говорит о том, что ответ был точно успешным. Но, заметьте, что клиент не может определить был ли код ответа от сервера 200 или 201, например.

По этой причине (непонятен изначальный ответ сервера) иногда не рекомендуется использовать 203 в качестве ответа, предпочитая 214 Transformation Applied.

204 No Content

Код ответа сигнализирует о том, что запрос был успешно принят, обработан и ответ не содержит тела.

Может быть использован, например, как ответ на успешное удаление ресурса:

Запрос:

DELETE /file.html HTTP/1.1
Host: example.com

Ответ:

HTTP/1.1 204 No Content

Отметим, что если на удаление ресурса сервер бы возвращал тело (например, вернул бы идентификатор ресурса или мета-информацию), то код ответа не был бы 204, а логичнее было бы использовать 200.

205 Reset Content

Данный статус говорит о том, что сервер выполнил запрос клиента и сообщает клиенту, что надо сбросить введенные пользователем данные. Никакие данные не должны передаваться в ответе (в теле ответа).

Используется, например, для того, чтобы облегчить пользователю ввод новой информации в форме. Клиент заполнил форму, после происходит отправка введенных данных в запросе, а затем механизм ввода данных сбрасывается для следующей записи, чтобы пользователь мог легко перейти к отправке новых данных.

206 Partial Content

Добавился в стандарт HTTP 1.1 вместе с возможностью частичной загрузки данных.

Статус код 206 Partial Content возвращается сервером для того, чтобы показать, что запрос успешно обработан и тело запроса содержит запрашиваемый кусок данных.

Как клиент может сообщить серверу информацию какую именно часть данных он хочет скачать? Разумеется, с помощью заголовков! Заголовок Range показывает диапазон в байтах. Заголовок Content-Range указывает на то, какой раздел был включен в ответе, а запрошенные данные будут содержаться в теле ответа.

GET /videos/sample.mp4 HTTP/1.1
Host: www.example.re
Range: bytes=25000-75000

Ответ:

HTTP/1.1 206 Partial Content
Content-Type: video/mp4
Content-Length: 25000
Content-Range: bytes 25000-75000/100000

<50,000 bytes of video data will follow>

Ответ также может содержать и несколько диапазонов.

226 IM Used

Введено в RFC 3229 для дополнения протокола HTTP поддержкой дельта-кодирования.

Заголовок A-IM от клиента был успешно принят и сервер возвращает содержимое с учётом указанных параметров. A-IM здесь значит Accepted Instance Manipulations.

3xx

Перенаправление указывает, что перед выполнением запроса необходимо выполнить дополнительные действия. Например, документ можно взять из кэша, либо сообщить клиенту, что документ сменил URL.

300 Multiple Choices

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

Доступные варианты перечислены в заголовках Link. Если есть ответ по умолчанию или у сервера есть предпочтительный выбор, он может указать это в заголовке Location.

Запрос:

GET /tech-news HTTP/1.1
Host: www.example.re

Ответ:

HTTP / 1.1
300
Multiple
Choices
Link: </
leading/news.html>
;rel = "alternate"
Link: </
bleeding/news.html>
;rel = "alternate"
Location: </
leading/news.html>
Content - Type
:
text / html
Content - Length
:
164

< h2 > Choose
from
one
of
the
following < /h2>
<ul>
    <li>
        <a href=/leading/news.html>Leading edge news</a>
        <li>
            <a href=/bleeding/news.html>Bleeding edge news</a>
</ul>

301 Moved Permanently

Данный статус говорит о том, что запрашиваемый ресурс был перенесен и теперь располагается в ином месте. Новый URI указывается в заголовке Location и может использоваться клиентом для автоматического перенаправления.

Поскольку изменение не является временным, клиент должен обновить свои собственные ссылки на новое местоположение.

Это сообщение может быть отправлено серверами, которые мигрировали в новый домен или реорганизовали свою внутреннюю файловую структуру.

Запрос:

GET /news.html HTTP/1.1
Host: www.example.re

Ответ:

HTTP/1.1 301 Moved Permanently
Location: http//www.example.re/feeds/news.html
Content-Type: text/html; charset=UTF-8
Content-Length: 150

<h1>The Newsfeed has moved</h1>
<body>
The newsfeed has moved permanently to <a href=/feeds/news.html>here</a>. Please update your bookmarks.
</body>

302 Found

Данный статус также известен под названием Moved Temporarily.

Статус говорит о том, что запрашиваемый ресурс временно перенесен и располагается в ином месте. Новый URI указывается в заголовке Location и клиент должен повторить запрос по новому адресу.

Поскольку изменение является временным, клиент не должен обновлять свои собственные ссылки на новое местоположение, а должен продолжать обращаться к конечной точке, отправившей 302, на случай, если что-то изменится.

Поисковые системы могут интерпретировать URI, возвращающий код состояния 302 Found в течение длительного периода времени, как равный коду состояния 301 Moved Permanently и рассматривать его как таковой.

Запрос:

GET /news.html HTTP/1.1
Host: www.example.re

Ответ:

HTTP/1.1 302 Found
Location: http//www.example.re/testing/news.html
Content-Type: text/html
Content-Length: 167

<h1>The Newsfeed has moved</h1>
<body>
The site is currently under development and the newsfeed has temporarily moved to <a href=/testing/news.html>here</a>.
</body>

303 See Other

Код состояния 303 See Other обычно возвращается в результате POST, PUT или DELETE. По сути, это означает, что результат запроса можно найти по другому адресу. Чтобы получить новый ресурс, клиент должен использовать новый запрос GET с указанным местоположением.

Запрос:

DELETE /tasks/314 HTTP/1.1
Host: www.example.re

Ответ:

HTTP/1.1 303 See Other
Location: http//www.example.re/confirmation/delete.html

304 Not Modified

Код состояния возвращается сервером, чтобы указать на успешный запрос, у которого нет необходимости отправлять данные, связанные с соответствующим ресурсом. По сути, это то же самое, что и код состояния 200 OK с включенным определенным заголовком:

  1. If-Match
  2. If-None-Match
  3. If-Modified-Since
  4. If-Unmodified-Since
  5. If-Range

Для этого кода ответа нет тела сообщения.

Предназначен для экономии траффика: поскольку серверу не нужно повторно передавать данные, которые уже есть у клиента.

305 Use Proxy

Является устаревшим из-за соображений безопасности. Используя этот код состояния, сервер может указать клиенту, что он должен подключиться к прокси и повторить там тот же запрос.

306 Switch Proxy

Зарезервирован и не используется.

Идея состоит в том, что если клиент уже использовал прокси-сервер, этот ответ можно использовать, чтобы сообщить клиенту, что клиент должен начать использовать новый прокси-сервер.

Часто говорят еще 306 Unused, например, в некоторых библиотеках этот код так и записан.

Интересно посмотреть, что в RFC крайне мало упоминаний про 306.

307 Temporary Redirect

По сути аналогичен 302 Found тем, что сообщает клиенту о временном перенаправлении в другое место для доступа к запрошенному ресурсу.

Статус 307 Temporary Redirect работает так же, как и код состояния 302 Found, за исключением того, что код состояния 307 специально гарантирует, что метод HTTP и тело сообщения не будут изменены в последующем HTTP-запросе.

308 Permanent Redirect

Схож с 301 Moved Permanently.

Когда получен код состояния 308 Permanent Redirect, клиенты должны обновить свои сохраненные ссылки на новый URI. Это будет указано в HTTP-заголовке Location и может использоваться клиентом для автоматического перенаправления.

Код состояния 308 Permanent Redirect отличается от кода состояния 301 Moved Permanently тем, что от клиента требуется сделать идентичный HTTP-запрос к указанному местоположению, тогда как 301 Moved Permanently позволяет клиенту изменить метод HTTP-запроса.

4xx

Класс ошибок означает, что запрос не может быть выполнен из-за ошикби клиента, например, проблем с синтаксисом запроса.

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

400 Bad Request

Это наиболее общая клиентская ошибка, которая обычно возвращается сервером, чтобы указать, что клиент сделал что-то не так. Не все случаи клиентских ошибок могут быть описаны HTTP кодом и в подобных ситуациях сервер может вернуть статус 400 Bad Request в качестве универсального ответа.

В теле может содержаться более точная информация о том, что именно пошло не так.

Причин, почему может быть получен код 400, огромное количество, например:

  1. Ошибка в URL, например, был передан невалидный символ
  2. При загрузке файла оказалось, что он слишком велик, чтобы его сохранить.
  3. При регистрации на форуме вы указали невалидный почтовый адрес или телефон

Главное, что объединяет эти ошикби - это то, что это ошибка на клиенте. И пока клиент сам не исправит запрос положительного ответа не будет.

Запрос:

GET /index{15}.html HTTP/1.1
Host: www.example.re

Ответ:

HTTP/1.1 400 Bad Request
Content-Type: text/html; charset=UTF-8
Content-Length: 132

<html>
  <head>
    <title>Malformed URL<\title>
  </head>
  <body>
    <p>Invalid characters in HTTP request</p>
  </body>
</html>

401 Unauthorized

Данный статус — это ошибка клиента, которая возвращается сервером, чтобы указать, что запрос должен быть аутентифицирован, а соответствующие учетные данные для входа еще не получены.

Например, перейти по ссылке, которую вам скинул друг, а эта ссылка указывает на его корзину в онлайн-магазине. В таком случае вам может быть возвращен статус 401, чтобы показать, что вы пытаетесь получить ресурс, доступ к которому может быть только у авторизованного пользователя.

Когда сервер отправляет обратно 401, он также должен отправить обратно заголовок WWW-Authenticate. Этот заголовок сообщает клиенту, какую схему аутентификации ожидает сервер. Схемы можно посмотреть в Authentication Scheme Registry.

Запрос:

GET /documents/tech-news HTTP/1.1
Host: www.example.re

Ответ:

HTTP/1.1 401 Unauthorized
WWW-Authenticate: Basic; realm=”Documents”
WWW-Authenticate: Mutual

Далее уже в соответствии со схемой и требованиями шлется новый запрос, включающий заголовок авторизации:

GET /documents/tech-news HTTP/1.1
Host: www.example.re
Authorization: Basic RXhhbXBsZTphaQ==

После чего:

HTTP/1.1 200 OK
Content-Type: application/pdf
Content-Length: 25000

<PDF document included in message body>

402 Payment Required

Зарезервирован и не используется.

Первоначальная идея могла заключаться в том, что коммерческие веб-сайты и API-интерфейсы хотели бы иметь способ по умолчанию сообщать, что HTTP-запрос может быть повторен после того, как пользователь оплатил услугу. Однако это догадка, а RFC предполагает, что использовать этот статус не рекомендуется, поскольку в будущем он может получить более точное определение, что может сделать существующие сайты несовместимыми.

403 Forbidden

Статус говорит о том, что клиент пытается выполнить запрос, который ему не разрешен по ряду причин. Возможно, у пользователя нет необходимых прав или неподходящая роль (например, он пытается зайти в панель администратора, не являясь администратором), или он вошел в систему с неправильными учетными данными.

GET /tech-news/confidential.pdf HTTP/1.1
Host: www.example.re

Ответ:

HTTP/1.1 403 Forbidden

404 Not Found

Это распространенная и общая ошибка клиента, которая возвращается сервером, чтобы указать, что ресурс не может быть найден по указанному адресу. Когда ресурс не существует, никогда не существовал или если сервер не хочет, чтобы клиент знал, что ресурс существует.

Если сервер хочет сообщить, что ресурса больше нет и больше никогда не будет, 410 Gone может быть более подходящим выбором.

Часто можно встретить, когда ответ 404 неправильно используется как успешный ответ на запрос DELETE. Логика этого заключается в том, что ресурс больше не существует после удаления, поэтому сервер должен сообщить об этом состоянии.

Однако, на мой взгляд, это технически неправильно. Любой ответ из серии 4xx всегда означает, что произошла клиентская ошибка. Поэтому успешные запросы DELETE должны получить ответ 200 OK или 204 No Content.

Запрос:

GET /documents/formula.pdf HTTP/1.1
Host: www.example.re

Ответ:

HTTP/1.1 404 Not Found
Content-Type: text/html

<h1>404 Not found</h1>

405 Method Not Allowed

Статус должен возвращаться сервером, когда определенный метод HTTP не поддерживается ресурсом.

Это отличается от 403 Forbidden, так как 403 предполагает, что сервер может поддерживать HTTP-запрос, но у клиента нет необходимых прав для выполнения HTTP-запроса, а 405 Method Not Allowed означает, что метод HTTP просто не поддерживается. Например, клиент делает POST-запрос к ресурсу, где POST не реализован или не имеет смысла.

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

HTTP/1.1 405 Method Not Allowed
Content-Type: text/html
Allow: GET, HEAD, OPTIONS, PUT

<h1>405 Try another method!</h1>

406 Not Acceptable

Статус 406 Not Acceptable может быть отдан сервером в случае, когда клиент запрашивает конкретное представление ресурса, которое сервер не поддерживает.

Клиент задает требуемые параметры через заголовки:

  1. Accept

    Указывает тип содержимого. Например, сервер может предоставить либо обычный текст, либо HTML-представление.

  2. Accept-Language

    Указывает какой язык предпочитает клиент

  3. Accept-Charset

    Указывает кодировку

  4. Accept-Encoding

    Указывает какой тип сжатия они поддерживают

  5. A-IM (смотрите про 226 IM Used)

Запрос, где клиент хочет получить ресурс на французком языке:

GET /news HTTP/1.1
Host: www.example.re
Accept-Language: fr

Ответ:

HTTP/1.1 406 Method Not Acceptable
Content-Type: text/html
Content-Length: 242

<html>
  <head>
    <title>French Language Not Available</title>
  </head>
  <body>
   <p>Please choose a supported language:</p>
    <p><a href="/news/news-de.html">German</a></p>
    <p><a href="/news/news-en.html">English</a></p>
   </body>
</html>

407 Proxy Authentication Required

Статус возвращается в случае, если требуется аутентификация на прокси-сервере. Это похоже на 401 Unauthorized, но для прокси.

408 Request Timeout

В ситуации, когда клиент инициировал запрос, но не передал его полностью (например, у него нестабильное интернет соединение), то сервер может отправить 408 и тем самым сказать, что он больше не хочет ждать запроса и разрывает соединение.

Ответ будет включать заголовок Connection: closed, указывающий, что он был закрыт.

Клиент может попытаться повторить запрос, как только получит этот ответ.

409 Conflict

Используется тогда, когда запрос был действительным, но текущее состояние сервера препятствует его выполнению.

Например, если клиент отвечает на сообщение, которое было удалено, целевой ресурс больше не находится в совместимом состоянии, и сервер может вернуть этот статус.

410 Gone

Когда получено сообщение со статусом 410 Gone, это говорит клиенту о том, что адрес был действительным в какой-то момент, но ресурс больше не существует.

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

Использование 410 может быть полезным, потому что это сигнализирует другим людям, ссылающимся на вас, что ссылка не работает и ее следует удалить. В то время как 404 — это ошибка по умолчанию для отсутствующих ресурсов, и это может просто означать, что владелец сайта переместил контент и не установил правильные перенаправления.

Т.е. 410 это более явная, скажем, уверенная ошибка 404. Когда мы демонстрируем намерение, что ресурса нет и не будет по этому адресу.

411 Length Required

Данный статус означает, что запрос должен быть повторно отправлен с HTTP-заголовком Content-Length. Запросы HTTP обычно используют этот заголовок для указания длины тела сообщения, хотя это не всегда необходимо. Например, при Chunked Transfer Coding, когда присутсвует заголовок Transfer-Encodingи для него задано значение chunked, в таком случае Content-Length не требуется.

Если сервер не поддерживает эту функцию, либо сервер хочет знать размер передаваемых данных, он может сообщить об этом, отправив обратно 411 Length Required.

Запрос:

PUT /docs HTTP/1.1
Host: www.example.re
Content-Type: applications/pdf

<PDF file included as message body>

Ответ:

HTTP/1.1 411 Length Required

412 Precondition Failed

В HTTP можно выполнять условные запросы. Это запросы, которые выполняются только при соблюдении некоторых условий. Условия передаются в заголовках.

Пример условного заголовка: If-Unmodified-Since.

Запрос:

POST /blog/update?postid=111&task=reply HTTP/1.1
Host: www.example.re
If-Unmodified-Since: Fri, 1 Jan 2021 00:00:00 GMT
Content-Type: text/plain
Content-Length: 45

<Message body contains reply-text from the client>

Ответ:

HTTP/1.1 412 Precondition Failed
Content-Type: text/html
Content-Length: 182

<html>
  <head>
    <title>Blog Update Error</title>
  </head>
  <body>
   <p>The post has changed since you last viewed it, so your reply will not be recorded.</p>
  </body>
</html>

413 Payload Too Large

Статус говорит о том, что клиент отправляет слишком большой запрос.

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

Изображения, например, могут иметь излишне высокое разрешение и могут быть значительно меньше, не влияя на предполагаемое использование. Вместо того, чтобы взять на себя ответственность за изменение изображения (например, сжатия), сервер отказывает в приеме файла.

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

Если эта ошибка временная, сервер может включить заголовок Retry-After, чтобы указать клиенту, что он должен просто повторить попытку через определенное время. Например, если у клиента есть квота на загрузку, и она была превышена.

Важно разделять тип ошибок. Если причина ошибки в том, что на сервере закончилось дисковое пространство (т.е. это не клиентская ошибка, а серверная, это разработчик/администратор не предусмотрели, что место может закончится), вместо этого следует использовать 507 Insufficient Storage.

414 URI Too Long

Статус, как можно понять из названия, говорит о том, что переданный URI слишком большой.

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

Исходя из ограничений браузеров, рекомендуется попробовать не превышать 2000 символов. При превышении этого размера сервер может ответить 414 статусом.

415 Unsupported Media Type

Когда сервер получает запрос с телом, которое не понимает, он должен вернуть 415 Unsupported Media Type. Например, для запроса POST или PUT с неизвестным заголовком Content-Type или Content-Encoding.

  1. Если Content-Type не поддерживается, используйте 415.
  2. Если запрос не поддается разбору (неверный JSON, XML), используйте 400 Bad Request.
  3. Если запрос можно распарсить, но конкретное содержимое тела было неправильным (из-за проверки или по какой-то другой причине), лучше вернуть статус 422 Unprocessable Entity.

416 Range Not Satisfiable

Как уже было сказано ранее, клиент может запрашивать частичные данные от сервера. Например, клиенту могут понадобиться только первые 5 минут видео или последние 100 строк файла/ресурса.

HTTP-клиенты и серверы могут это делать используя заголовок Content-Range.

В ситуациях, когда клиент запросил диапазон, который не имеет смысла, может быть возвращен данный статус 416 Range Not Satisfiable. Например, размер файла был 1024 байта, а клиент запросил 2000-3000 байт.

Запрос:

GET /documents/main HTTP/1.1
Host: www.example.re
Content-Range: bytes=1000-2000

Ответ:

HTTP/1.1 416 Range Not Satisfiable
Content-Range: bytes */512

417 Expectation Failed

Клиент может использовать заголовок Expect, чтобы сообщить серверу, что он требует определенного поведения от сервера. Сервер выдает ошибку 417 Expecation Failed, когда он сталкивается с заголовком Expect, который он не понимает или не поддерживает.

Например:

POST /foo/bar HTTP/1.1
Content-Type: application/gzip
Content-Length: 12345678765
Expect: 100-continue

Этот запрос предназначен для загрузки большого файла. Клиент сообщает серверу, что он ожидает, что сервер сначала ответит 100 Continue.

Если сервер поддерживает это, он сначала вернет этот ответ 100 Continue, который сообщает клиенту, что запрос был понят, поддержан и можно продолжить загрузку.

Если сервер не поддерживает эту функцию, он должен ответить 417.

418 I'm a teapot

Сообщение об ошибке 418 I’m a teapot было разработано как одна из первоапрельских шуток. Этот код состояния не используется, но поддерживается многими библиотеками. Некоторое время назад была предпринята попытка удалить эту ошибку, чтобы номер можно было переиспользовать, однако это встретило сопротивление и привело к созданию инициативы Save 418. Таким образом, сообщение и код состояния остаются.

422 Unprocessable Entity

Код состояния 422 Unprocessable Entity введен был в рамках спецификации WebDAV, являющейся расширением HTTP. Однако, в отличие от других кодов, введенных вместе с WebDAV, используется и вне этого протокола в построении Web API.

Код 422 подразумевает, что сервер понял общий синтаксис запроса, но его содержание (какая-то часть тела) было неверным. Например, сервер может ожидать POST-запросов, использующих формат application/json. Если тело запроса невалидно, то более целесообразно отправить обратно код состояния 400, но если запрос валиден, но не проходит проверку (например, с помощью json-схемы), возврат 422 может быть более лучшим вариантом.

Правила использования приведены в разборе кода 415.

425 Too Early

Когда клиент HTTP устанавливает соединение с сервером HTTPS, он использует TLS для создания безопасного соединения. Создание безопасного соединения может занять много времени, особенно когда между сервером и клиентом большая задержка.

Клиенты могут оптимизировать это время, отправляя кучу данных в самом начале процесса, до того, как будет полностью настроено полное соединение TLS.

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

В этих ситуациях он вернет код состояния 425 Too Early.

Скорее всего вам, как разработчику, никогда не придется иметь дело с этим кодом состояния, если только вы не создаете HTTP-серверы с нуля.

426 Upgrade Required

Код состояния 426 Upgrade Required используется, когда сервер хочет сообщить клиенту, что он должен использовать более новую версию или другой протокол для связи с сервером.

Ответ включает поле заголовка ответа Upgrade, чтобы указать требуемый(е) протокол(ы). Это сообщение связано с сообщением 101 Switching Protocols, которое отправляется в ответ на запрос клиента об обновлении соединения сервером.

Запрос:

GET /tech-news HTTP/1.1
Host: www.example.re

Ответ:

HTTP/1.1 426 Upgrade Required
Upgrade: HTTP/2, HTTP/3
Connection: upgrade
Content-Type: text/html
Content-Length: 154

<html>
  <head>
    <title>Protocol Not Supported</title>
  </head>
  <body>
   <p>This service supports HTTP/2 and HTTP/3 only.</p>
  </body>
</html>

Это может быть полезно, когда хотят заставить клиента использовать более новую версию.

428 Precondition Required

Ранее уже было проговорено про условные запросы (например, про 412 статус код): используя заголовки If-Match, If-None-Match, If-Modified-Since и If-Unmodified-Since.

Однако эти заголовки не являются обязательными. Если сервер хочет заставить клиента использовать их, то сервер может вернуть 428 Precondition Required.

Эти требования могут быть использованы для уменьшения случаев потери данных, таких как проблема "потерянных обновлений". Когда вы запросили состояние ресурса и решили его изменить, но при этом в это же время кто-то еще может делать то же самое. Чтобы изменения не перезатерли друг друга можно потребовать использовать условные заголовки.

Отличие от 412 статуса заключается в том, что 428 код - это требование отправить заголовки, в то время как 412 - это когда отправленные заголовки не соответствуют текущему состоянию ресурса.

429 Too Many Requests

Если необходимо ограничить количество запросов, которые делают клиенты, то можно использовать код состояния 429 Too Many Requests, чтобы сообщить клиенту, что он превысил допустимое количество запросов.

С помощью заголовка Retry-After можно сообщить клиенту, когда он может снова делать запросы, но это необязательно.

Запрос:

GET /current-news HTTP/1.1
Host: www.example.re

Ответ:

HTTP/1.1 429 Too Many Requests
Content-Type: text/plain
Retry-After: 3600

You exceeded the limit. Try again in an hour

Часто используется для задач rate limiting.

431 Request Header Fields Too Large

Этот статус можно получить, если общий размер всех заголовков превышает некоторый предел или если отдельные заголовки слишком велики.

Допустимый размер заголовка зависит от веб-сервера. Обычно значение по умолчанию - это 8kb.

Если клиент видит ошибку 431, он может удалить какие-то из заголовков и повторить попытку. Наиболее очевидным кандидатом на это может быть удаление файлов cookies.

451 Unavailable For Legal Reasons

Cервер может отказаться обрабатывать запрос клиента по юридическим причинам, в таком случае он верент код состояния 451 Unavailable For Legal Reasons. Например, из-за государственной цензуры.

Это более конкретная версия 403 Forbidden.

Когда ресурс заблокирован, сервер также должен ответить заголовком Link, содержащим информацию о том, кто заблокировал запрос.

Это должно относиться к организации, ответственной за блокировку, а не к организации, устанавливающей политику (поэтому, например, в случае с Youtube это будет относиться к Google).

HTTP/1.1 451 Unavailable For Legal Reasons
Link: <https://www.example.re/legaldept>; rel=”blocked-by”
Content-Type: text/html
Content-Length: 174

<html>
  <head>
    <title>Publication Ban</title>
  </head>
  <body>
   <p>The content that you have requested is unavailable due to a government-ordered publication ban.</p>
  </body>
</html>

5xx

Информирование о случаях неудачного выполнения операции по вине сервера, например из-за нехватки ресурсов, программных ошибок и т.д.

Статусы 5xx показывают клиенту, что с его запросом все было хорошо, ошибка произошла не из-за неправильного запроса, а по вине самого сервера.

В отличие от 4xx ошибок, в данном случае клиент не может самостоятельно решить проблему, поэтому, возможно, стоит даже связаться с технической поддержкой сервиса, который вы пытаетесь использовать.

В самом простом случае стоит повторить запрос позднее.

500 Internal Server Error

Это универсальное сообщение об ошибке сервера, которое носит общий характер и обычно используется, если более конкретное сообщение недоступно, т.е. нет более конкретной ошибки, подходящей для проблемы.

Многие обработчики ошибок на стороне сервера автоматически преобразуют любое неперехваченное исключение в этот код ошибки.

501 Not Implemented

Сервер может вернуть 501 Not Implemented, если он не поддерживает определенный функционал (не поддерживает метод запроса).

Ситуация достаточно похожа на ту, когда мы разбирали 405 Method Not Allowed. Но есть разница. Учитывая, что 5xx — это ошибки на стороне сервера, а ошибки 4xx — на стороне клиента, то получение 405 означает, что метод никогда не должен был вызываться клиентом, в то время как 501 может означать, что метод должен был сработать, но сервер (пока или еще) имеет неполный функционал.

Может быть использован во время разработки новых API в качестве "заглушки" для методов, которые еще не реализованы, но будут.

502 Bad Gateway

Как уже отмечалось выше, иногда между клиентом и сервером находится еще шлюз - прокси.

И в ситуации, когда прокси запрос клиента принял, а сервер, которому запрос проксировался, вернул некорректный ответ, то будет возвращено 502. Если прокси-сервер не получает никакого HTTP-ответа от вышестоящего сервера, то более подходящим является возврат кода состояния 504 Gateway Timeout.

Причин, почему сервер может некорректно отработать запрос несколько, например, соединение было разорвано или возникли проблемы с маршрутизацией.

503 Service Unavailable

Этот статус может быть получен клиентом, когда сервер перегружен или иным образом не может обработать запрос. Возможно, сервер просто еще стартует, либо приложение частично не работает.

Когда этот статус возвращается, сервер может дополнительно включить заголовок Retry-After, чтобы сообщить клиенту, когда следует повторить запрос.

Некоторые сайты возвращают код состояния 503 Service Unavailable во время обслуживания сайта, что является рекомендуемым способом гарантировать, что обслуживание не повлияет на рейтинг поиска

504 Gateway Timeout

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

Это похоже на 502 Bad Gateway, за исключением того, что 502 возвращается, когда прокси-сервер получил неверный ответ, в то время как 504 возвращается тогда, когда прокси-сервер вообще не получил ответа (или получил слишком поздно).

505 HTTP Version Not Supported

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

Попробуйте отправить запрос с версией HTTP/51.0. Забавно, что многие сайты отправляют в ответ именно 400 Bad Request, хотя некоторые вполне себе возвращают 505.

507 Insufficient Storage

Этот код состояния был представлен спецификацией WebDAV. Он позволяет серверу сообщить клиенту, что его операция (например, PUT или POST) не может быть выполнена, потому что она слишком велика для размещения на диске.

Несмотря на то, что статус был введен для WebDAV, его можно использовать вне серверов WebDAV.

Однако, на мой взгляд, применимость данного статуса крайне ограничена, если вообще нужна.

Поскольку 507 — это именно ошибка на стороне сервера, то это как бы указывает на то, что повторив запрос позднее клиент вполне сможет выполнить свой запрос. Т.е. мы сообщаем, что это у нас на сервере место закончилось и мы решаем эту проблему, а как решим, то клиент сможет повторить запрос успешно.

В реальности же, скорее всего, клиент либо сохраняет слишком большой ресрус (который мы не хотим у себя сохранять в виду величины), в таком случае лучше вернуть более подходящую ошибку 413 Payload Too Large. Либо сообщить клиенту, что он исчерпал свою квоту, расширив которую, он сможет сохранить свой ресурс. Возвращать же что-то типа "у нас переполнены диски", мне кажется, смысла не имеет.

511 Network Authentication Required

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

Вы можете встретить такое поведение, например, при подключении к Wi-Fi в кафе или в метро.

HTTP/1.1 511 Network Authentication Required
Content-Type: text/html

<html>
  <head>
     <title>Network Authentication Required</title>
     <meta http-equiv="refresh"
           content="0; url=https://login.example.net/">
  </head>
  <body>
     <p>You need to <a href="https://login.example.net/">
     authenticate with the local network</a> in order to gain
     access.</p>
  </body>
</html>

Самостоятельная работа

Откройте браузер и найдите там инструменты веб-разработчика.

В браузере Google Chrome это можно сделать так:

web инструменты

Теперь перейдите на вкладку Network и откройте любой сайт, например, githib.com.

После этого посмотрите на запросы, их заголовки и попробуйте объяснить, что за заголовки и почему там участвуют.

github loading

Безопасность

Протокол является открытым и не защищен. Именно поэтому стандартом сейчас является расширение протокола HTTP для поддержки шифрования в целях повышения безопасности: HTTPS.

Заключение

Протокол HTTP 1.1 - это текстовый stateless протокол (он не хранит состояние). Основная мощь протокола в его гибкости и расширяемости, что обеспечено огромным количеством заголовков. При этом пользователь может вводить собственные заголовки. Благодаря заголовкам, протокол гибок и расширяем.

В HTTP 1.1 были введены:

  1. Виртуальные хосты

    Позволило быть на одном IP и порту несколько DNS имен.

  2. Persistent-Connection

    Connection: Keep-Alive по умолчанию.

  3. Chunked transfer encoding

    Позволяет отправлять ответ не зная его полного размера и не буферизуя его на стороне сервера. Отправляем по кусочкам.

  4. Range request

    Запрос только части ресурса. Например, позволяет в несколько потоков скачать ресурс.

  5. Сжатие

    Сжимается только тело запроса, заголовки не сжимаются.

  6. Кэширование

Полезные ссылки

  1. Web-технологии. Протокол HTTP | Технострим
  2. HTTP Wikipedia
  3. HTTP протокол - Иван Бибилов
  4. HTTP и HTTPS - Вячеслав Бирюков
  5. Простым языком об HTTP
  6. HyperText Transfer Protocol (HTTP)
  7. Series of posts on HTTP status codes
  8. Mozilla. Обзор протокола HTTP
  9. RFC 2616 HTTP 1.1
  10. RFC 7231 Hypertext Transfer Protocol (HTTP/1.1): Semantics and Content
  11. RFC 5785 Defining Well-Known Uniform Resource Identifiers (URIs)
  12. RFC 5789 PATCH
  13. HTTP GET with request body
  14. Wikipedia URI
  15. RFC 7233 Hypertext Transfer Protocol (HTTP/1.1): Range Requests
  16. HTTP Conditional Requests
  17. Don't hurt HTTP: If-(None-)Match & the 412 HTTP status code
  18. RFC Additional HTTP Status Codes
  19. RFC HTTP Extensions for Web Distributed Authoring and Versioning (WebDAV)
  20. Список кодов состояния HTTP
  21. Что такое CDN и как это работает?
  22. Wikipedia Cookie
  23. Dmitry Ketov WEB.1: HTTP протокол
  24. URI, URL, URN. Что это, чем отличаются
  25. [HTTP API & REST] Терминология. Мифология REST. Составляющие HTTP-запроса