Схема функционирования HTTP-сообщений и возможные риски. Типы HTTP-запросов и философия REST Какой протокол уровня приложений использует такие типы сообщений как get put и post

Схема функционирования HTTP-сообщений и возможные риски. Типы HTTP-запросов и философия REST Какой протокол уровня приложений использует такие типы сообщений как get put и post

612

HTTP PUT:

PUT помещает файл или ресурс в определенный URI, и именно на этом URI. Если в этом URI уже есть файл или ресурс, PUT заменяет этот файл или ресурс. Если там нет файла или ресурса, PUT создает его. PUT - idempotent , но, как ни парадоксально, ответы PUT не подлежат кэшированию.

HTTP POST:

POST отправляет данные на конкретный URI и ожидает ресурс на том, что URI для обработки запроса. Веб-сервер в этот момент может определить, что делать с данными в контексте указанного ресурса. Метод POST не равен idempotent , однако ответы POST : кэшируются, если сервер устанавливает соответствующие заголовки Cache-Control и Expires.

Официальный HTTP RFC определяет POST быть:

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

Разница между POST и PUT:

Сам RFC объясняет разницу ядра:

Фундаментальное различие между POST и PUT запросов отражено в различное значение Request-URI. URI в запросе POST идентифицирует ресурс, который будет обрабатывать заключенный объект. Этот ресурс может быть принимающим данные процессом, шлюзом к другому протоколу или отдельным объектом, который принимает аннотации. В отличии от этого, URI в запросе PUT идентифицирует объекта, включенный в запросе - агент пользователя знает, что URI является предназначен и сервер НЕ ДОЛЖЕН попытки применить запрос к некоторым другому ресурсу. Если сервер желает, чтобы запрос был применен к другому URI , он ДОЛЖЕН отправить 301 (перемещенный постоянный) ответ; пользовательский агент МОЖЕТ затем сделать своим собственным решением относительно того, перенаправить запрос или нет.

Используя правильный метод, несвязанные в стороне:

Я получаю в последнее время довольно раздражает популярное заблуждение веб-разработчиков, что POST используется для создания ресурса, а PUT используется для обновления/изменения.

Если вы посмотрите на странице 55 RFC 2616 («Протокол передачи гипертекста - HTTP/1.1»), Section 9.6 («PUT»), вы увидите, что PUT на самом деле для:

Метод PUT запрашивает, чтобы закрытый объект хранился в запрошенном Request-URI.

Там также удобный пункт, чтобы объяснить разницу между POST и PUT:

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

В нем ничего не говорится о различии между обновлением/созданием, потому что это не то, о чем речь. Речь идет о разнице между этим:

Obj.set_attribute(value) # A POST request.

Obj.attribute = value # A PUT request.

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

9

Это кажется бесполезным грубым и педантичным менее полезным способом. В примере PUT, который вы цитируете, новый объект в RESTful api является «новой» записью и доступен в этом месте. Не вызывает сомнений, является ли хороший выбор дизайна, позволяющий подменям быть такими, как это (я думаю, что это не идеальный вариант), но даже если бы вы использовали подвид, чтобы нападать на большую полезную информацию. В большинстве случаев описание, как обычно говорится, является отличным заявлением о содержании RFC, суммированном и заявлении обычной и обычной практики. Кроме того, вам не будет больно быть вежливым. - tooluser 06 апр. 15 2015-04-06 23:49:56

60

1) GET: - Используется, когда клиент запрашивает ресурс на веб-сервере.

2) HEAD: - Используется, когда клиент запрашивает некоторую информацию о ресурсе, но не запрашивает сам ресурс.

3) POST: - Используется, когда клиент отправляет информацию или данные на сервер, например, заполняя онлайн-форму (т. Е. Отправляет на веб-сервер большое количество сложных данных).

4) PUT: - Используется, когда клиент отправляет заменяющий документ или загружает новый документ на веб-сервер под URL-адресом запроса.

5) УДАЛИТЬ: - Используется, когда клиент пытается удалить документ с веб-сервера, идентифицированный URL-адресом запроса.

6) TRACE: - Используется, когда клиент запрашивает доступные прокси или промежуточные серверы, изменяющие запрос, чтобы объявить себя.

7) ОПЦИИ: - Используется, когда клиент хочет определить другие доступные методы для извлечения или обработки документа на веб-сервере.

8) CONNECT: - Используется, когда клиент хочет установить прозрачное соединение с удаленным хостом, как правило, для обеспечения SSL-шифрованной связи (HTTPS) через HTTP-прокси.

15

  • УДАЛЕНИЕ: Удаляет данные с сервера.
  • TRACE: Предоставляет способ проверить, какой сервер получает. Он просто возвращает то, что было отправлено.
  • ОПЦИИ: Позволяет клиенту получать информацию о методах запросов, поддерживаемых службой. Соответствующим заголовком ответа является «Разрешить» с поддерживаемыми методами. Также используется в CORS в качестве предполетного запроса информировать сервер о фактическом методе запроса и спрашивать о пользовательских заголовках.
  • HEAD: возвращает только заголовки ответов.
  • CONNECT: Используется браузером, когда он знает, что он говорит с прокси, и окончательный URI начинается с https: //. Цель CONNECT состоит в том, чтобы разрешить сквозной зашифрованный сеанс TLS, поэтому данные нечитабельны для прокси.
  • PHP provides support for the HTTP PUT method used by some clients to store files on a server. PUT requests are much simpler than a file upload using POST requests and they look something like this:

    PUT /path/filename.html HTTP/1.1

    This would normally mean that the remote client would like to save the content that follows as: /path/filename.html in your web tree. It is obviously not a good idea for Apache or PHP to automatically let everybody overwrite any files in your web tree. So, to handle such a request you have to first tell your web server that you want a certain PHP script to handle the request. In Apache you do this with the Script directive. It can be placed almost anywhere in your Apache configuration file. A common place is inside a block or perhaps inside a block. A line like this would do the trick:

    Script PUT /put.php

    This tells Apache to send all PUT requests for URIs that match the context in which you put this line to the put.php script. This assumes, of course, that you have PHP enabled for the .php extension and PHP is active. The destination resource for all PUT requests to this script has to be the script itself, not a filename the uploaded file should have.

    With PHP you would then do something like the following in your put.php. This would copy the contents of the uploaded file to the file myputfile.ext on the server. You would probably want to perform some checks and/or authenticate the user before performing this file copy.

    Example #1 Saving HTTP PUT files

    /* PUT data comes in on the stdin stream */
    $putdata = fopen ("php://input" , "r" );

    /* Open a file for writing */
    $fp = fopen ("myputfile.ext" , "w" );

    /* Read the data 1 KB at a time
    and write to the file */
    while ($data = fread ($putdata , 1024 ))
    fwrite ($fp , $data );

    /* Close the streams */
    fclose ($fp );
    fclose ($putdata );
    ?>

    13 years ago

    A Case Study: To set up publishing with Netscape 7.2 Composer to Apache/PHP, no need to use CGI (which I tried unsuccessfully for too long) or to alter Apache"s httpd.conf. I needed only to click Publish As, fill in put2disk.php as the filename (where its contents are the below), and fill in that file"s dir as the "Publishing address".
    XAMPP 1.4.14: Apache/2.0.54 (Win32) mod_ssl/2.0.54 OpenSSL/0.9.7g PHP/5.0.4.

    //file_put_contents ("get_def.out", print_r (get_defined_vars(), TRUE)); // debugging

    // Two slurp methods: (a) didn"t work, (b) did.
    //$stdin_rsc = fopen("php://input", "r");
    //$putdata="";
    //while ($putdata .= fread($stdin_rsc, 1024)); // a. Hangs the "Publishing..." dialog.
    //while (!feof($stdin_rsc)) $putdata.=fread($stdin_rsc, 8192); // b. Worked, but file_get_contents is faster.
    //fclose($stdin_rsc);

    // All that"s nec:
    $putdata=file_get_contents("php://input"); // Not php://stdin! (When the ability to see error messages isn"t available, the doc (this manual page) needs to be more accurate.)

    file_put_contents("stdin.out",$putdata);
    ?>

    15 ответов

    HTTP PUT:

    PUT помещает файл или ресурс в определенный URI и точно в этот URI. Если в этом URI уже есть файл или ресурс, PUT заменяет этот файл или ресурс. Если там нет файла или ресурса, PUT создает его. PUT idempotent , но парадоксально ответы PUT не кэшируемы.

    HTTP POST:

    POST отправляет данные в определенный URI и ожидает, что ресурс в этом URI обрабатывает запрос. Веб-сервер в этот момент может определить, что делать с данными в контексте указанного ресурса. Метод POST не idempotent , однако ответы POST могут быть кэшируемыми, если сервер устанавливает соответствующие заголовки Cache-Control и Expires.

    Официальный HTTP RFC определяет POST как:

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

    Разница между POST и PUT:

    Сам RFC объясняет основную разницу:

    Основное различие между Запросы POST и PUT отражены в различный смысл Request-URI. URI в запросе POST идентифицирует ресурс, который будет обрабатывать закрытую сущность. Что ресурсом может быть прием данных процесс, шлюз для некоторых других протокол или отдельный объект, который принимает аннотации. Напротив, URI в запросе PUT идентифицирует объект, прилагаемый к запросу - пользовательский агент знает, что такое URI и сервер НЕ ДОЛЖЕН попытка применить запрос к другой ресурс. Если сервер желает что запрос будет применен к другой URI, он ДОЛЖЕН отправить 301 (перемещенный постоянный) ответ; пользовательский агент МОЖЕТ затем сделать его собственное решение относительно того, следует ли перенаправить запрос.

    Использование правильного метода, не связанного в стороне:

    Только семантика.

    Предполагается, что HTTP PUT принимает тело запроса, а затем сохраняет его на ресурсе, идентифицированном URI.

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

    PUT , например . Помещенный в URI влияет именно на этот URI. POST для URI может вообще иметь какой-либо эффект.

    Чтобы привести примеры ресурсов стиля REST:

    "POST/books" с кучей информации о книге может создать новую книгу и ответить новым URL-адресом, идентифицирующим эту книгу: "/books/5".

    "PUT/books/5" придется либо создать новую книгу с идентификатором 5, либо заменить существующую книгу с идентификатором 5.

    В стиле non-resource POST можно использовать практически для всего, что имеет побочный эффект. Еще одно отличие состоит в том, что PUT должен быть идемпотентным - несколько PUT одинаковых данных для одного и того же URL-адреса должны быть точными, если несколько POST могут создавать несколько объектов или что-то, что делает ваше POST-действие.

    1) GET: - используется, когда клиент запрашивает ресурс на веб-сервере.

    2) HEAD: - используется, когда клиент запрашивает некоторую информацию о ресурсе, но не запрашивает сам ресурс.

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

    4) PUT: - Используется, когда клиент отправляет заменяющий документ или загружает новый документ на веб-сервер под URL-адресом запроса.

    5) DELETE: - Используется, когда клиент пытается удалить документ с веб-сервера, указанный URL-адресом запроса.

    6) TRACE: - Используется, когда клиент просит доступные прокси или промежуточные серверы изменять запрос, чтобы объявить себя.

    7) ОПЦИИ: - Используется, когда клиент хочет определить другие доступные методы для извлечения или обработки документа на веб-сервере.

    8) CONNECT: - Используется, когда клиент хочет установить прозрачное соединение с удаленным хостом, как правило, для обеспечения SSL-шифрованной связи (HTTPS) через прокси-сервер HTTP.

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

    Согласно RFC , разница между PUT и POST находится в URI запроса. URI, идентифицированный POST, определяет объект, который будет обрабатывать запрос POST. URI в запросе PUT включает объект в запрос. Таким образом, POST /v1/coffees/orders означает создание нового ресурса и возврат идентификатор для описания ресурса. Напротив, PUT /v1/coffees/orders/1234 означает обновление ресурса, идентифицированного " 1234 ", если оно существует; иначе создайте новый порядок и используйте URI orders/1234 , чтобы идентифицировать его.

    PUT and POST can both be used to create or update methods. The usage of the method depends on the idempotent behavior expected from the method as well as the location of the resource to identify it.

    POST считается чем-то вроде метода типа factory. Вы включаете данные с ним, чтобы создать то, что хотите, и все, что находится на другом конце, знает, что с ним делать. PUT используется для обновления существующих данных по указанному URL-адресу или для создания чего-то нового, когда вы знаете, что будет URI, и он еще не существует (в отличие от POST, который создаст что-то и вернет URL-адрес при необходимости).

    В последнее время меня очень раздражает популярное заблуждение веб-разработчиков, что POST используется для создания ресурса, а PUT используется для обновления/изменения.

    Если вы посмотрите на страницу 55 RFC 2616 ("Протокол передачи гипертекста - HTTP/1.1"), раздел 9.6 ("PUT"), вы увидите что PUT действительно для:

    Метод PUT запрашивает, чтобы закрытый объект был сохранен в поставляемом Request-URI.

    Theres также удобный абзац, чтобы объяснить разницу между POST и PUT:

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

    В нем ничего не говорится о различии между обновлением/созданием, потому что это не о чем. О различии между этим:

    Obj.set_attribute(value) # A POST request.

    Obj.attribute = value # A PUT request.

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

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

    Чтобы создать ресурс на сервере, используйте POST.

    Чтобы получить ресурс, используйте GET.

    Чтобы изменить состояние ресурса или обновить его, используйте PUT.

    Чтобы удалить или удалить ресурс, используйте DELETE.

    Насколько я понимаю все это, то, если сравнить PUT и POST операциями в MySQL, то POST - это INSERT, а PUT - UPDATE or INSERT

    Расмотрим на примере форума. В нём есть темы и сообщения. Мы делаем запросы в тему hello

    POST /topic/hello?message = Здесь POST /topic/hello?message = был POST /topic/hello?message = Вася

    Первый запрос создаст (INSERT ) тему hello с сообщением "Здесь", остальные два запроса тоже создадут (INSERT ) новые сообщения в теме. В результате у нас получится, что тема hello содержит: Здесь был Вася.

    PUT /topic/hello?message = Здесь PUT /topic/hello?message = был PUT /topic/hello?message = Вася

    Первый запрос создаст (INSERT ) тему hello с сообщением "Здесь", остальные два запроса обновят (UPDATE ) сообщение в теме. В результате у нас получится, что тема hello содержит: Вася.

    Идемпотентность PUT здесь проявляется в том, что количество сообщений в базе при последующих операциях остаётся неизменным . Касательно ссылок - карта сайта будет оставаться неизменной. Будет обновляться лишь содержимое тем.

    или: каждый запрос POST /article/hello будет создавать новую главу в статье hello. Первый запрос создаст саму статью.

    каждый запрос PUT /article/hello будет обновлять ЕДИНСТВЕННУЮ главу в статье hello. Первый запрос создаст саму статью.

    Вот, что нам должен возвращать GET, если мы делали POST

    GET /topic/hello 201 Здесь был Вася

    В этом случае у нас также будут доступны и эти URI

    GET /topic/hello/1 201 Здесь GET /topic/hello/2 201 был GET /topic/hello/3 201 Вася

    Вот, что нам должен вернуть GET, если мы делали PUT

    GET /topic/hello 201 Вася

    В этом случае у нас будет доступна только одна URI

    GET /topic/hello/1 201 Вася GET /topic/hello/2 404 GET /topic/hello/3 404

    EXAMPLE #2 Пример с пользователями.

    POST /user/eugen?age=7 POST /user/eugen?age=10 POST /user/eugen?age=5

    Создаст 3 пользователя с именем eugen и возрастом 7, 10, 5, соответственно.

    PUT /user/eugen?age=7 PUT /user/eugen?age=10 PUT /user/eugen?age=5

    Будет создан только один пользователь с именем eugen с возрастом 5

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

    Отсюда и Ваш пример String userId = this.request["USER_ID"]; с сохранением значения в переменной. Сколько раз вы бы не ложили (PUT ) значения в переменную - переменная всегда будет одна.

    Отсюда родился EXAMPLE #3

    Не знаю на сколько эта аналогия верна, но думаю это утверждение будет верно:

    POST: push $variable, value; -- в итоге массив значений PUT: $variable = value; -- в итоге одно значение

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

    Кстати, вот нашел хороший ресурс, по поводу безопасности и идемпотентности

    При разработке процедуры отправки на сайт информации из 1С с версией платформы 8.3.9.2170 столкнулся с проблемой: разработчик сайта предоставил мне возможность записывать нужную информацию только при помощи HTTP запроса методом PUT.

    Недолго думая, я набросал простенький код:

    Соединение = Новый HTTPСоединение("www.mysite.ru"); Заголовки = Новый Соответствие; Заголовки["Content-Type"] = "application/x-www-form-urlencoded"; Запрос = Новый HTTPЗапрос("/api/order_items/93076?order_item=30", Заголовки); Соединение.Записать(Запрос);

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

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

    Сразу же выяснилась странная вещь: вышеприведенный код генерирует не PUT, а HEAD запрос!

    В логах апача я увидел следующее:

    127.0.0.1 - - "HEAD /api/order_items/93076?order_item=30 HTTP/1.1"

    Я немного удивился (в руководстве ведь было черным по белому написано PUT), но не растерялся - можно ведь вызвать метод напрямую:

    Соединение.ВызватьHTTPМетод("PUT",Запрос);

    В логах то же самое:

    127.0.0.1 - - "HEAD /api/order_items/93076?order_item=30 HTTP/1.1"

    "Может быть я что-то не так делаю?" - задал я себе вопрос. Но в интернете и в мануалах не было никаких подсказок. Что ж, метод научного тыка еще никто не отменял. Для начала я попробовал сделать так:

    Соединение.ВызватьHTTPМетод("фывфыв",Запрос);

    В логах получил:

    127.0.0.1 - - "?????? /api/order_items/93076?order_item=30 HTTP/1.1"

    Любопытно, значит 1С заменяет конкретно метод PUT (чем же он 1С не угодил?).

    После еще нескольких попыток я пришел к варианту:

    Соединение.ВызватьHTTPМетод("PUT ",Запрос);

    В логах получил:

    127.0.0.1 - - "PUT /api/order_items/93076?order_item=30 HTTP/1.1"

    И уже этот вариант отработал на сайте и все остались довольны.

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

    Соединение = Новый HTTPСоединение("www.mysite.ru"); Заголовки = Новый Соответствие; Заголовки["Content-Type"] = "application/x-www-form-urlencoded"; Запрос = Новый HTTPЗапрос("/api/order_items/93076?order_item=30", Заголовки); Запрос.УстановитьТелоИзСтроки("", КодировкаТекста.UTF8, ИспользованиеByteOrderMark.НеИспользовать); Соединение.Записать(Запрос);

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

    Вывод следующий: PUT запрос без тела платформа 1С считает ошибочным и заменяет метод на HEAD.

    Любопытно что POST запрос без тела 1С никак не отслеживает и не превращает в GET, проверял ради спортивного интереса.

    Как сказал бы всем известный Вовочка из знаменитого анекдота: "Где логика?".

    Надеюсь кому-то моя публикация сбережет несколько часов жизни в поисках ответа. =)))



    top