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

Код ответа HTTP для POST, когда ресурс уже существует

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

Я определил API, чтобы клиенты могли создавать или изменять объекты с помощью PUT:

PUT /objects/{id} HTTP/1.1
...

{json representation of the object}

Идентификатор {id} - это идентификатор объекта, поэтому он является частью Request-URI.

Теперь я также рассматриваю возможность создания клиентов с помощью POST:

POST /objects/ HTTP/1.1
...

{json representation of the object, including ID}

Поскольку POST понимается как операция "добавить", я не уверен, что делать, если объект уже существует. Должен ли я обрабатывать запрос как запрос модификации или мне нужно вернуть код ошибки (который)?

4b9b3361

Ответ 1

Мое чувство 409 Conflict является наиболее подходящим, однако редко встречается в дикой природе:

Запрос не может быть выполнен из-за конфликта с текущим состоянием ресурса. Этот код разрешен только в ситуациях, когда ожидается, что пользователь сможет разрешить конфликт и повторно отправить запрос. Тело ответа ДОЛЖНО включать достаточную информацию, чтобы пользователь мог распознать источник конфликта. В идеальном случае объект ответа будет содержать достаточную информацию для пользователя или агента пользователя для устранения проблемы; однако это может быть невозможно и не требуется.

Конфликты чаще всего возникают в ответ на запрос PUT. Например, если использовалось управление версиями, а объект PUT включал изменения в ресурс, который конфликтует с теми, которые были сделаны с помощью более раннего (стороннего) запроса, сервер может использовать ответ 409, чтобы указать, что он не может выполнить запрос, В этом случае объект ответа, скорее всего, будет содержать список различий между двумя версиями в формате, определяемом ответом Content-Type.

Ответ 2

Лично я иду с расширением WebDAV 422 Unprocessable Entity.

Шаблоны REST описывают его как

Код состояния 422 Unprocessable Entity означает, что сервер понимает тип содержимого объекта запроса (следовательно, код состояния 415 Unsupported Media Type не подходит), а синтаксис объекта запроса является правильным (таким образом, код состояния 400 Bad Request неуместно), но не смог обработать содержащиеся инструкции.

Ответ 3

В соответствии с RFC 7231 можно использовать 303 See Other. Если результатом обработки POST будет эквивалентный  представление существующего ресурса.

Ответ 4

"302 Найдено" звучит логично для меня. И RFC 2616 говорит, что на него можно ответить за другие запросы, кроме GET и HEAD (и это, безусловно, включает POST)

Но он по-прежнему не дает посетителю перейти к этому URL-адресу, чтобы получить этот "найденный" ресурс, RFC. Чтобы заставить его перейти непосредственно к реальному URL-адресу "Найденный", следует использовать "303 См." Прочее ", что имеет смысл, но заставляет другой вызов ПОЛУЧИТЬ следующий URL-адрес. С хорошей стороны этот GET можно кэшировать.

Я думаю, что я использовал бы "303 See Other" . Я не знаю, могу ли я ответить с "вещью", найденной в теле, но я хотел бы сделать это, чтобы сохранить один обратный ход на сервере.

ОБНОВЛЕНИЕ:. После повторного чтения RFC, я все же считаю, что код несуществующий "4XX + 303 найденный" должен быть правильным. Однако "409 Conflict" - лучший существующий код ответа (как указано в @Wrikken), возможно, включая заголовок Location, указывающий на существующий ресурс.

Ответ 5

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

Чтобы немного рассказать о ответе Wrikken, я думаю, что вы можете использовать либо 409 Conflict, либо 403 Forbidden в зависимости от ситуации - короче говоря, используйте ошибку 403, когда пользователь может ничего не делать, чтобы разрешить конфликт и завершить запрос (например, они не могут отправить запрос DELETE для явного удаления ресурса) или использовать 409, если что-то возможно сделать.

10.4.4 403 Запрещено

Сервер понял запрос, но отказывается его выполнять. Авторизация не поможет, и запрос НЕ ДОЛЖЕН повториться. Если метод запроса не был HEAD, и сервер хочет обнародовать почему запрос не был выполнен, СЛЕДУЕТ описать причину за отказ в юридическом лице. Если сервер не хочет эта информация доступна клиенту, код состояния 404 (Not Найдено).

В настоящее время кто-то говорит "403", и на ум приходит проблема с разрешениями или аутентификацией, но спецификация говорит, что в основном сервер говорит клиенту, что он не собирается этого делать, не спрашивайте его снова, и вот почему клиент не должен.

В отношении PUT vs. POST... POST следует использовать для создания нового экземпляра ресурса, когда у пользователя нет средств для создания или отсутствия идентификатора ресурса. PUT используется, когда идентификатор ресурса известен.

9.6 PUT

...

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

он ДОЛЖЕН отправить 301 (перемещенный постоянный) ответ; пользовательский агент МОЖЕТ затем принять собственное решение относительно того, перенаправлять ли запрос.

Ответ 6

Я не думаю, что вы должны это сделать.

POST, как вы знаете, модифицирует коллекцию и используется для СОЗДАНИЯ нового элемента. Итак, если вы отправляете идентификатор (я думаю, что это не очень хорошая идея), вам следует изменить коллекцию, т.е. Изменить элемент, но это сбивает с толку.

Используйте его для добавления элемента без id. Это лучшая практика.

Если вы хотите зафиксировать ограничение UNIQUE (а не идентификатор), вы можете ответить 409, как вы можете сделать в запросах PUT. Но не идентификатор.

Ответ 7

Я думаю, что для REST вам просто нужно принять решение о поведении для этой конкретной системы, и в этом случае я думаю, что "правильный" ответ был бы одним из двух ответов, приведенных здесь. Если вы хотите, чтобы запрос останавливался и вел себя так, как если бы клиент допустил ошибку, которую он должен исправить, прежде чем продолжить, используйте 409. Если конфликт действительно не так важен и он хочет сохранить запрос, тогда ответьте, перенаправив клиент к найденному объекту. Я думаю, что правильные API REST должны перенаправлять (или, по крайней мере, предоставлять заголовок местоположения) конечной точке GET для этого ресурса после POST в любом случае, поэтому это поведение даст последовательный опыт.

EDIT: Также стоит отметить, что вы должны рассмотреть PUT, так как вы предоставляете идентификатор. Тогда поведение простое: "Мне все равно, что там сейчас, поставьте там эту вещь". Значение, если ничего не существует, оно будет создано; если что-то там, то оно будет заменено. Я думаю, что POST более подходит, когда сервер управляет этим идентификатором. Разделение двух концепций в основном говорит вам, как с этим бороться (т.е. PUT является идемпотентным, поэтому он всегда должен работать до тех пор, пока полезная нагрузка проверяется, POST всегда создает, поэтому, если есть столкновение идентификаторов, то 409 будет описывать этот конфликт).

Ответ 9

Еще одно потенциальное лечение - использование PATCH. PATCH определяется как что-то, что изменяет внутреннее состояние и не ограничивается добавлением.

PATCH решит проблему, разрешив вам обновлять уже существующие элементы. См.: RFC 5789: PATCH

Ответ 10

Почему не 202 Принято? Это запрос OK (200 с), ошибок клиента (400) не было.

Из 10 Определения кода состояния:

"202 принят. Запрос принят для обработки, но обработка не завершена."

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

Я склоняюсь к тому, чтобы метать 202 и возвращать аналогичный контент тому, что возвратил бы GET /{resource}/{id}.

Ответ 11

Что относительно 208 - http://httpstatusdogs.com/208-already-reported? Это вариант?

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

Ответ 12

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

Извините мое невежество, но я не понимаю, почему все игнорируют код "300", в котором четко сказано "множественный выбор" или "неоднозначный"

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

https://tools.ietf.org/html/rfc7231#section-6.4.1