Разное

Метод put: PUT & POST при написании API — Хабр Q&A

Содержание

HTTP запрос: заголовки HTTP запроса, методы HTTP запроса, строка HTTP запроса, ресурсы HTTP запроса, примеры запросов

Привет, читатель блога ZametkiNaPolyah.ru! Продолжим знакомиться с протоколом HTTP в рубрике серверы и протоколы и ее разделе HTTP протокол. В этой записи ты узнаешь всё что можно про запросы HTTP протокола.  Для начала мы с тобой разберем структуру HTTP запроса, затем мы посмотрим, что собой представляет строка HTTP запроса, потом мы поговорим с тобой о методах HTTP запроса и ты узнаешь, собственно, что такое метод. Потом мы плавно перейдем к идентификаторам ресурса в HTTP запросе (Request-URI, если не совсем понятно), после чего мы с тобой разберем поля заголовков HTTP запроса и в конце этой записи мы с тобой разберем пару примеров HTTP запросов, которые, для закрепления прочитанного, ты можешь написать самостоятельно, как делает твой браузер, через который ты зашел на этот сайт.

HTTP запрос: заголовки HTTP запроса, методы HTTP запроса, строка HTTP запроса, ресурсы HTTP запроса, примеры запросов

Структура HTTP запроса

Содержание статьи:

Если вы хотите узнать всё про протокол HTTP, обратитесь к навигации по рубрике HTTP протокол.  HTTP запрос – это HTTP сообщение, которое клиент посылает HTTP серверу.  Обычно HTTP запрос содержит:

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

Вот так выглядит общий синтаксис (общая структура HTTP запроса):

Request       = Request-Line              ; *( general-header         ; | request-header         ; | entity-header )        ; CRLF [ message-body ]          ;

Request       = Request-Line              ;

 

*( general-header         ;

 

| request-header         ;

 

| entity-header )        ;

 

CRLF

 

[ message-body ]          ;

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

Строка HTTP запроса

Строка HTTP запроса начинается с маркера/метки метода, после которой следует URI запрашиваемого ресурса (если не понятно, читай про параметры HTTP протокола), версия HTTP протокола и символ CRLF, который означает конец строки HTTP запроса. Синтаксис строки HTTP запроса:

Request-Line   = Method SP Request-URI SP HTTP-Version CRLF

Request-Line   = Method SP Request-URI SP HTTP-Version CRLF

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

HTTP метод запроса

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

НомерHTTP метод запроса и его описание
1GET Метод HTTP запроса GET используется для получения информации с сервера по указанному URI. HTTP запросы, использующие метод GET должны получать только данные и не должны оказывать никакого влияния на эти данные.
2HEAD Принцип работы метода HEAD в HTTP запросе аналогичен методу GET, но метод HEAD не передает тело сообщения (HTTP объект).
3POST HTTP запрос POST используется для отправки данных на HTTP сервер, например, когда вы заполняете HTML форму на сайте.
4PUT HTTP запросы с методом PUT сохраняются под запрашиваемым URI. То есть метод PUT используется для замены контента.
5DELETE Метод DELETE при HTTP запросе позволяет запросить сервер удалить данные ресурса, указанного в URI.
6CONNECT HTTP запрос с методом CONNECT позволяет установить  туннель к серверу, который указан в URI.
7OPTIONS HTTP запрос с методом OPTION позволяет получить параметры для связи с ресурсом.
8TRACE При HTTP запросе с методом TRACE можно отследить то, что происходит с вашими запросами.

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

URI HTTP запроса (Request-URI). Запрашиваемый URI

URI HTTP запроса (Request-URI) или запрашиваемый URI для нас в большинстве случаев это обычный URL, который дает однозначное понимание HTTP серверу к какому ресурсу мы хотим обратиться:

Request-URI    = «*» | absoluteURI | abs_path

Request-URI    = «*» | absoluteURI | abs_path

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

absoluteURI URI необходим при HTTP запросе в том случае, когда HTTP запрос производится при помощи прокси-сервера. Прокси-сервер может передать этот запрос HTTP серверу, а может дать ответ из своего кэша, пример absoluteURI в HTTP запросе:

GET http://www.w3.org/pub/WWW/TheProject.html HTTP/1.1

GET http://www.w3.org/pub/WWW/TheProject.html HTTP/1.1

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

Рассмотрим третий вид URI в HTTP запросе, наиболее общую и часто встречаемую форму Request-URI, данную форму Request-URI используют для идентификации ресурса на конечном HTTP сервере, при этом

абсолютный путь URI передается в HTTP запросе, как Request-URI, а вот сетевое расположение ресурса передается в поле Host HTTP заголовка. Пример:

GET /pub/WWW/TheProject.html HTTP/1.1 Host: www.w3.org

GET /pub/WWW/TheProject.html HTTP/1.1

 

Host: www.w3.org

Обратите внимание, что абсолютный путь не может быть пустым; если оригинальный URI пуст, то он должен запрашиваться как «/» (корневой каталог сервера). Первоначальный сервер должен декодировать Request-URI (кодирование в HTTP), чтобы правильно интерпретировать запрос. Серверам следует отвечать на недопустимые Request-URI соответствующим кодом состояния.

В запросах, которые передаются далее, прокси-сервера никогда не должны перезаписывать часть «abs_path» запрашиваемого URI (Request-URI), за исключением случая, отмеченного выше, когда пустой abs_path заменяется на «*», независимо от внутренней реализации прокси-сервера.

Первоначальные HTTP/1.1 сервера должны учитывать, что точный ресурс, идентифицированный интернет-запросом определяется как Request-URI, так и полем заголовка Host. Первоначальный сервер, который различает ресурсы, основанные на запрошенном хосте (иногда называемые виртуальными хостами или vanity hostnames) должен использовать следующие правила для определения запрошенного в HTTP/1.1 запросе ресурса:

  1. Если Request-URI — это absoluteURI, то хост — это часть Request-URI. Любое значение поля заголовка Host в запросе ДОЛЖНО игнорироваться (напомню про требования HTTP).
  2. Если Request-URI — не absoluteURI, а запрос содержит поле заголовка Host, то хост определяется значением поля заголовка Host.
  3. Если хоста, определенного правилами 1 или 2 не существует на сервере, код состояния ответа должен быть 400 (Испорченный Запрос, Bad Request).

Получатели HTTP/1.0 запроса, в котором недостает поля заголовка Host, могут пытаться использовать эвристику (например, исследовать путь в URI на предмет уникальности на каком-либо из хостов) чтобы определить какой точно ресурс запрашивается.

Поля заголовка HTTP запроса

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

request-header = Accept | Accept-Charset | Accept-Encoding | Accept-Language | Authorization | From | Host | If-Modified-Since | If-Match | If-None-Match | If-Range | If-Unmodified-Since | Max-Forwards | Proxy-Authorization | Range | Referer | User-Agent

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

request-header = Accept

 

| Accept-Charset

 

| Accept-Encoding

 

| Accept-Language

 

| Authorization

 

| From

 

| Host

 

| If-Modified-Since

 

| If-Match

 

| If-None-Match

 

| If-Range

 

| If-Unmodified-Since

 

| Max-Forwards

 

| Proxy-Authorization

 

| Range

 

| Referer

 

| User-Agent

Никто не запрещает вам ввести свои собственные поля заголовков HTTP запроса, если вы решите написать свой собственный клиент или HTTP сервер.

Примеры HTTP запросов

Давайте теперь разберем несколько примеров HTTP запросов. Пример HTTP запроса для получения простой HTML страницы: представим, что на сайте example.org лежит HTML документ, который называется hello.htm, http запрос для него будет выглядеть примерно следующим образом:

GET /hello.htm HTTP/1.1 User-Agent: Mozilla/4.0 (compatible; MSIE5.01; Windows NT) Host: www.example.com Accept-Language: ru-ru Accept-Encoding: gzip, deflate Connection: Keep-Alive

GET /hello.htm HTTP/1.1

 

User-Agent: Mozilla/4.0 (compatible; MSIE5.01; Windows NT)

 

Host: www.example.com

 

Accept-Language: ru-ru

 

Accept-Encoding: gzip, deflate

 

Connection: Keep-Alive

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

POST /cgi-bin/process.cgi HTTP/1.1 User-Agent: Mozilla/4.0 (compatible; MSIE5.01; Windows NT) Host: www.example.com Content-Type: application/x-www-form-urlencoded Content-Length: length Accept-Language: ru-ru Accept-Encoding: gzip, deflate Connection: Keep-Alive   licenseID=string&content=string&/paramsXML=string

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

POST /cgi-bin/process.cgi HTTP/1.1

 

User-Agent: Mozilla/4.0 (compatible; MSIE5.01; Windows NT)

 

Host: www.example.com

 

Content-Type: application/x-www-form-urlencoded

 

Content-Length: length

 

Accept-Language: ru-ru

 

Accept-Encoding: gzip, deflate

 

Connection: Keep-Alive

 

 

 

licenseID=string&content=string&/paramsXML=string

В стартовой строке указан URL /cgi-bin/process.cgi – он будет использован для обработки данных, которые мы передадим серверу в запросе, на такой запрос мы даже получим от сервера ответ. Content-Type сообщает серверу о том, что данные, которые мы хотим передать серверу – это простая HTML форма.

Методы REST / HTTP: POST против PUT против PATCH

Каждый HTTP-запрос состоит из метода (иногда называемого глаголом ), который указывает действие, которое должно быть выполнено на идентифицированном ресурсе.

При создании веб-сервисов RESTful HTTP-метод POST обычно используется для создания ресурса, а PUT — для обновления ресурса. Хотя это нормально в большинстве случаев, также может быть целесообразно использовать PUT для создания ресурса. PATCH является альтернативой для обновлений ресурсов, поскольку позволяет частичные обновления.

В целом мы можем сказать:

  • POST-запросы создают дочерние ресурсы на сервере, определяемом URI. POST также используется как общая операция обработки
  • PUT-запросы создают или заменяют ресурс на клиентском URI
  • PATCH запрашивает обновление частей ресурса на определенном клиентом URI

Но давайте посмотрим немного подробнее и посмотрим, как эти глаголы определены в спецификации HTTP. Соответствующей частью здесь является раздел 9 HTTP RFC (2616) .

ПОЧТА

RFC описывает функцию POST как:

Метод POST используется для запроса, чтобы исходный сервер принял объект, включенный в запрос, в качестве нового подчиненного ресурса, идентифицируемого Request-URI в строке запроса.

Это позволяет клиенту создавать ресурсы, не зная URI для нового ресурса. Например, мы можем отправить запрос POST в / projects, чтобы создать новый проект. Теперь сервер может создать проект в качестве нового подчиненного объекта / project , например: / projects / 123 . Таким образом, при использовании POST для создания ресурса сервер может определить URI (и, как правило, ID) вновь создаваемых ресурсов.

Когда сервер создал ресурс, он должен ответить кодом состояния 201 (Создано) и заголовком Location, который указывает на вновь созданный ресурс.

Например:

Запрос:

1

2

3

4

5

6

7

POST /projects HTTP/1.1

Content-Type: application/json

 

{

    "name": "my cool project",

    ...

}

Отклик:

1

2

HTTP/1.1 201 Created

Location: https:

ПОСТ не идемпотент . Поэтому отправка одних и тех же запросов POST несколько раз может привести к созданию нескольких ресурсов. В зависимости от ваших потребностей это может быть полезной функцией. Если нет, вы должны провести некоторую проверку и убедиться, что ресурс создается только один раз на основе некоторых пользовательских критериев (например, имя проекта должно быть уникальным ).

RFC также сообщает нам:

Действие, выполняемое методом POST, может не привести к ресурсу, который может быть идентифицирован с помощью URI. В этом случае либо 200 (ОК), либо 204 (Нет содержимого) — это соответствующий статус ответа, в зависимости от того, включает ли ответ объект, который описывает результат.

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

ПОЛОЖИТЬ

Основное различие между POST и PUT заключается в различном значении URI запроса. HTTP RFC говорит:

URI в запросе POST идентифицирует ресурс, который будет обрабатывать вложенную сущность. [..] Напротив, URI в запросе PUT идентифицирует объект, заключенный в запросе [..], и сервер НЕ ДОЛЖЕН пытаться применить запрос к какому-либо другому ресурсу.

Для запросов PUT клиент должен знать точный URI ресурса. Мы не можем отправить запрос PUT в / projects и ожидать, что новый ресурс будет создан в / projects / 123 . Вместо этого мы должны отправить запрос PUT непосредственно в / projects / 123 . Поэтому, если мы хотим создать ресурсы с PUT, клиент должен знать (как генерировать) URI / ID нового ресурса.

В ситуациях, когда клиент может сгенерировать URI / ID ресурса для новых ресурсов, фактически PUT должен быть предпочтительнее POST. В этих случаях создание ресурса обычно идемпотентно , что является явным намеком на PUT.

Хорошо использовать PUT для создания и обновления ресурсов. Таким образом, отправка запроса PUT в / projects / 123 может создать проект, если он не существует, или заменить существующий проект. Коды состояния HTTP должны использоваться для информирования клиента, если ресурс был создан или обновлен.

HTTP RFC сообщает нам:

Если новый ресурс создан, сервер происхождения ДОЛЖЕН проинформировать пользовательский агент через ответ 201 (Создано). Если существующий ресурс модифицируется, то должны быть отправлены коды ответа 200 (ОК) или 204 (Нет содержимого), чтобы указать успешное завершение запроса.

Вообще говоря, если точный URI ресурса известен и операция идемпонентна , PUT обычно является лучшим выбором, чем POST. В большинстве случаев это делает PUT хорошим выбором для запросов на обновление.

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

PATCH

Метод HTTP PATCH определен в RFC 5789 как расширение ранее упомянутого HTTP RFC. В то время как PUT используется для замены существующего ресурса, PATCH используется для частичного изменения ресурса.

Цитируя RFC:

В PATCH, [..], вложенный объект содержит набор инструкций, описывающих, как ресурс, находящийся в данный момент на исходном сервере, должен быть модифицирован для создания новой версии. Метод PATCH влияет на ресурс, идентифицируемый Request-URI, и он также МОЖЕТ иметь побочные эффекты на других ресурсах;

Таким образом, PATCH, подобно POST, может также влиять на ресурсы, отличные от

Доступны ли методы PUT, DELETE, HEAD и т. д. В большинстве веб-браузеров?

Я видел пару вопросов здесь, как как отлаживать службы RESTful, в которой говорится:

к сожалению, тот же браузер не позволяет мне тестировать HTTP PUT, DELETE и в определенной степени даже HTTP POST.

Я также слышал, что браузеры поддерживают только GET и POST, из некоторых других источников например:

однако несколько быстрых тестов в Firefox показывают, что отправка PUT и DELETE запросы работают как ожидалось — the XMLHttpRequest завершается успешно, и запрос отображается в журналах сервера с правильный метод. Есть ли какой-то аспект в этом, которого мне не хватает, например, кросс-браузерная совместимость или неочевидные ограничения?

573

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *