Подтвердить что ты не робот

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

Точнее:

В соответствии с стилем отдыха, обычно предполагалось, что для операций CREATE, READ, UPDATE и DELETE (CRUD) следует использовать методы POST, GET, PUT и DELETE http.

Фактически, если мы придерживаемся определения методов http, вещь может быть не столь ясной.

В в этой статье объясняется, что:

Вкратце: используйте PUT тогда и только тогда, когда вы знаете как URL, где будет жить ресурс, так и весь контент ресурса. В противном случае используйте POST.

В основном потому, что

PUT - гораздо более ограничивающий глагол. Он берет полный ресурс и сохраняет его по заданному URL. Если раньше существовал ресурс, он заменяется; если нет, создается новый. Эти свойства поддерживают идемпотентность, которая может быть выполнена не наивной операцией создания или обновления. Я подозреваю, что это может быть почему PUT определяется так, как он есть; это идемпотентная операция, которая позволяет клиенту отправлять информацию на сервер.

В моем случае я обычно выпускаю обновления, передавая все данные ресурса, поэтому я могу использовать PUT для обновлений, но каждый раз, когда я выдаю обновление, я сохраняю столбец LastUser и LastUpdate с идентификатором пользователя, который сделал модификацию и время od операции.

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

Saludos

SAS

4b9b3361

Ответ 1

Игнорируя комментарий о стиле REST, сопоставляющий CRUD с методами HTTP, это отличный вопрос.

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

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

Целая, полная дискуссия по ресурсам и частичным ресурсам, наконец, была описана в обновлении Спецификация HTTP

Исходный сервер ДОЛЖЕН отклонить любой PUT запрос, содержащий Поле заголовка Content-Range, так как оно могут быть неверно истолкованы как частичные контента (или может быть частичным контентом это ошибочно PUT как полное представление). Частичное содержание обновления возможны путем таргетинга на отдельно идентифицированный ресурс с состояние, которое перекрывает часть больший ресурс, или используя другой метод, который был определенную для частичного обновления (например, PATCH метод, определенный в [RFC5789]).

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

Ответ 2

Поскольку LastUser и LastUpdate не изменяются клиентом, я удаляю их из представления вашего ресурса в целом. Позвольте мне объяснить мои рассуждения на примере.

Скажем, что наш типичный пример API вернет клиенту следующее представление, когда будет предложено предоставить один ресурс:

GET /example/123

<?xml version="1.0" encoding="UTF-8" ?>
<example>
    <id>123</id>
    <lorem>ipsum</lorem>
    <dolor>sit amet</dolor>
    <lastUser uri="/user/321">321</lastUser>
    <lastUpdate>2011-04-16 20:00:00 GMT</lastUpdate>
</example>

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

PUT /example/123

<?xml version="1.0" encoding="UTF-8" ?>
<example>
    <id>123</id>
    <lorem>foobar</lorem>
    <dolor>foobaz</dolor>
    <lastUser>322</lastUser>
    <lastUpdate>2011-04-16 20:46:15 GMT+2</lastUpdate>
</example>

Поскольку API автоматически генерирует значения для LastUser и LastUpdate и не может принимать данные, предоставленные клиентом, наиболее подходящим ответом будет 400 Bad Request или 403 Forbidden (так как клиент не может изменять эти значения).

Если мы хотим быть совместимыми с REST и отправлять полное представление ресурса при выполнении запроса PUT, нам нужно удалить LastUser и LastUpdate из представления ресурса. Это позволит клиентам отправлять полный объект через PUT:

PUT /example/123

<?xml version="1.0" encoding="UTF-8" ?>
<example>
    <id>123</id>
    <lorem>foobar</lorem>
    <dolor>foobaz</dolor>
</example>

Теперь сервер примет полное представление, что он не содержит LastUpdate и LastUser.

Остается вопрос, как предоставить клиентам доступ к LastUpdate и LastUser. Если они им не нужны (и эти поля требуются только внутри API), мы в порядке, и наше решение отлично RESTful. Если, однако, клиентам нужен доступ к этим данным, самым чистым подходом будет использование HTTP-заголовков:

GET /example/123

...
Last-Modified: Sat, 16 Apr 2011 18:46:15 GMT
X-Last-User: /user/322
...

<?xml version="1.0" encoding="UTF-8" ?>
<example>
    <id>123</id>
    <lorem>foobar</lorem>
    <dolor>foobaz</dolor>
</example>

Использование пользовательского HTTP-заголовка не является идеальным, потому что пользовательские агенты должны быть обучены тому, как его читать. Если мы хотим предоставить клиентам доступ к тем же данным более простым способом, единственное, что мы можем сделать, это поместить данные в представление, и мы сталкиваемся с той же проблемой, что и в вашем исходном вопросе. Я бы хотя бы попытался смягчить его. Если тип контента, используемый API, является XML, мы можем поместить данные в атрибуты node вместо того, чтобы подвергать их непосредственно как значения node, т.е.:

GET /example/123

...
Last-Modified: Sat, 16 Apr 2011 18:46:15 GMT
...

<?xml version="1.0" encoding="UTF-8" ?>
<example last-update="2011-04-16 18:46:15 GMT" last-user="/user/322">
    <id>123</id>
    <lorem>foobar</lorem>
    <dolor>foobaz</dolor>
</example>

Таким образом мы, по крайней мере, избежим проблемы, когда клиент попытается отправить все узлы XML в последующий запрос PUT. Это не будет работать с JSON, и решение по-прежнему немного на грани идемпотентности (поскольку API будет по-прежнему игнорировать атрибуты XML при обработке запроса).

Еще лучше, поскольку Jonah указал в комментариях, если клиентам нужен доступ к LastUser и LastUpdate, они могут быть представлены как новые ресурс, связанный с оригиналом, например следующим образом:

GET /example/123

<?xml version="1.0" encoding="UTF-8" ?>
<example>
    <id>123</id>
    <lorem>foobar</lorem>
    <dolor>foobaz</dolor>
    <lastUpdateUri>/example/123/last-update</lastUpdateUri>
</example>

... и затем:

GET /example/123/last-update

<?xml version="1.0" encoding="UTF-8" ?>
<lastUpdate>
    <resourceUri>/example/123</resourceUri>
    <updatedBy uri="/user/321">321</updatedBy>
    <updatedAt>2011-04-16 20:00:00 GMT</updatedAt>
</lastUpdate>

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

Обратите внимание:
Я согласен с Darrel Miller взять вопрос, но я хотел бы предложить другой подход к нему, Обратите внимание, что этот подход не подкрепляется никакими стандартами/RFC/и т.д., Это просто другое решение проблемы.

Ответ 3

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

Итак:

Put = UPDATE

Post = INSERT

Надеюсь, это поможет в вашем конкретном случае.

Ответ 4

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

Используйте PUT, когда вы можете полностью обновить ресурс через определенный ресурс. Например, если вы знаете, что статья находится в http://example.org/article/1234, вы можете использовать новое представление ресурса этой статьи непосредственно через PUT на этом URL.

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