Код ответа 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 подразумевается как операция добавления, я не уверен, что делать, если объект уже существует. Должен ли я рассматривать запрос как запрос на изменение или я должен вернуть код ошибки (который)?

вопрос задан 29.09.2010
vmj
3104 репутация

15 ответов


  • 705 рейтинг

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

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

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

    ответ дан Wrikken, с репутацией 54407, 29.09.2010
  • 62 рейтинг

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

    REST Patterns описывает его как

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

    ответ дан Gareth, с репутацией 86936, 29.09.2010
  • 51 рейтинг

    В соответствии с RFC 7231 , 303 См. Другое МОЖЕТ быть использовано Если результат обработки POST будет эквивалентен представление существующего ресурса .

    ответ дан Nullius, с репутацией 1090, 9.11.2016
  • 16 рейтинг

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

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

    10. 4. 4 403 Запрещено

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

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

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

    9. 6 PUT

    . , ,

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

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

    ответ дан p0lar_bear, с репутацией 1343, 24.12.2015
  • 11 рейтинг

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

    Но он по-прежнему удерживает посетителя, переходящего по этому URL, чтобы получить этот ресурс «Найдено» в RFC. Чтобы перейти непосредственно к реальному «найденному» URL-адресу, нужно использовать «303 See Other», что имеет смысл, но заставляет другой вызов получить GET следующий URL-адрес. С хорошей стороны, этот GET кешируется.

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

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

    ответ дан alanjds, с репутацией 1935, 16.05.2012
  • 11 рейтинг

    А как насчет возвращения 418?

    Поскольку клиент просит сохранить сущность, которая уже существует на сервере, сервер, наконец, злится и думает, что он чайник, и возвращает: 418 I'm a teapot.

    Справочные материалы:

    ответ дан рüффп, с репутацией 3187, 20.07.2017
  • 8 рейтинг

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

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

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

    Если вы хотите захватить УНИКАЛЬНОЕ ограничение (не идентификатор), вы можете ответить 409, как вы можете сделать в запросах PUT. Но не удостоверение личности.

    ответ дан Alfonso Tienda, с репутацией 1863, 30.09.2014
  • 6 рейтинг

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

    РЕДАКТИРОВАТЬ: Стоит также отметить, что вы должны рассмотреть PUT, поскольку вы предоставляете ID. Тогда поведение простое: «Мне все равно, что там сейчас, положите эту вещь туда. "То есть, если там ничего нет, оно будет создано; если там что-то есть, оно будет заменено. Я думаю, что POST является более подходящим, когда сервер управляет этим ID. Разделение двух понятий в основном говорит вам, как с этим бороться (т.е. е. PUT является идемпотентом, поэтому он должен всегда работать, пока проверяется полезная нагрузка, POST всегда создает, поэтому, если есть конфликт идентификаторов, то 409 описал бы этот конфликт).

    ответ дан Sinaesthetic, с репутацией 5292, 27.10.2016
  • 6 рейтинг

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

    От 10 Определений кодов состояния :

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

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

    Я опираюсь на 202 и возвращаю содержимое, похожее на то, что вернул бы GET /{resource}/{id}.

    ответ дан Phillip Harrington, с репутацией 363, 17.03.2016
  • 4 рейтинг

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

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

    .
    ответ дан Martin Kersten, с репутацией 2700, 7.09.2015
  • 3 рейтинг

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

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

    Кажется, что 409 Conflict является наиболее распространенным ответом здесь, но, согласно спецификации, это означает, что ресурс уже существует, и новые данные, которые вы применяете к нему, несовместимы с его текущим состоянием. Если вы отправляете запрос POST, например, с уже введенным именем пользователя, оно фактически не конфликтует с целевым ресурсом, поскольку целевой ресурс еще не был опубликован. Это ошибка специально для контроля версий, когда существует конфликт между версией хранимого ресурса и запрашиваемой версией ресурса. Это очень полезно для этой цели, например, когда клиент кэширует старую версию ресурса и отправляет запрос на основе этой неверной версии, которая больше не будет условно допустимой. «В этом случае представление ответа, скорее всего, будет содержать информацию, полезную для объединения различий, основанных на истории изменений. «Запрос на создание другого пользователя с таким именем пользователя просто не обрабатывается, не имея никакого отношения к управлению версиями.

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

    ответ дан Grant Gryczan, с репутацией 390, 7.04.2018
  • 2 рейтинг

    А как насчет 208 - http: // httpstatusdogs. com / 208-уже сообщили ? Это вариант?

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

    ответ дан Fernando Ferreira, с репутацией 481, 31.07.2015
  • 2 рейтинг

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

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

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

    https: // tools. IETF. орг / HTML / rfc7231 # раздел-6. 4. 1

    ответ дан Hitin, с репутацией 177, 2.01.2017
  • 1 рейтинг

    Это все о контекст , а также кто отвечает за наличие дубликатов (сервер или клиент или оба)

    Если сервер только указывает на дубликат , посмотрите на 4xx:

    • 400 Bad Request - когда сервер не будет обрабатывать запрос, потому что это очевидная ошибка клиента
    • 409 Конфликт - если сервер не будет обрабатывать запрос, но причиной этого является не ошибка клиента

    Для неявной обработки дубликатов см. 2XX:

    • 200 ОК
    • 201 Создан

    , если сервер должен вернуть что-то , посмотрите на 3XX:

    • 302 найдено
    • 303 См. Другое

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

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

    ответ дан Sławomir Lenart, с репутацией 1575, 8.08.2018
  • 1 рейтинг

    Скорее всего это 400 Bad Request

    6. 5. 1. 400 неверный запрос


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

    Поскольку запрос содержит повторяющееся значение (значение, которое уже существует), его можно воспринимать как ошибку клиента. Необходимо изменить запрос до следующей попытки.
    Учитывая эти факты, мы можем сделать вывод, что HTTP STATUS 400 Bad Request.

    ответ дан Mohammed Safeer, с репутацией 8947, 6.08.2018