REST-API, правильный код состояния HTTP для недопустимого DELETE

Я разрабатываю RESTful API, который использует коды состояния и глаголы HTTP в качестве ключевых компонентов в общении.

На религиозном уровне это фанатичная сторона RESTafarian.

Эмпирическим правилом для определения кодов состояния HTTP является этот график или аналогичные ресурсы.

  • GET /api/documents/1 - 401 Пользователь не вошел в систему
  • GET /api/documents/1 - 200 У пользователя есть разрешение
  • GET /api/documents/1 - 403 У пользователя нет разрешения
  • DELETE /api/documents/1 - 204 Пользователи имеют разрешение
  • DELETE /api/documents/1 - 403 У пользователя нет разрешения
  • GET /api/documents/2 - 404 Разрешение пользователя не актуально, ресурс не существует
  • DELETE /api/documents/2 - 404 Разрешение пользователя не актуально, ресурс не существует
  • DELETE /api/documents/1 - 404 У пользователя есть разрешение, ресурс уже удален
  • DELETE /api/documents/1 - 404 У пользователей нет прав, ресурс уже удален

Цели:

  • Последовательность в использовании
  • Не раскрывать личную информацию через ошибки
  • Правильное использование кодов состояния для кэшей клиента или среднего уровня
  • Сбой раньше, сведение запросов к минимуму

В этой ситуации есть много разных кодов состояния на выбор (404, 403, 410, 405), и в моем случае я выбрал 403 на существующем ресурсе, если это не ваше, чтобы не очищать кеш, и 404 на всех не существующие ресурсы, чтобы сказать клиентам стереть эти данные.

Но мне не нравится переход с 403 на 404 на чужих ресурсах.

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

(Множество обсуждений REST и ответов в Интернете в целом сводятся к следующему: «Бросьте 400 плохих запросов, все равно никого не волнует», у меня нет проблемы, требующей быстрого решения или прагматичного взлома. Спасибо)


person Cleric    schedule 06.05.2014    source источник


Ответы (3)


Общий указатель: если ресурс существует, но пользователь не авторизован для выполнения операций с ним, вы должны вернуть 401 вместо 403:

401 Неавторизованный

Подобно 403 Forbidden, но специально для использования, когда аутентификация требуется, но она не удалась или еще не была предоставлена.

а также

403 Запрещено

Запрос был действительным, но сервер отказывается отвечать на него. В отличие от ответа 401 Unauthorized, аутентификация не имеет значения.

См. Также Правильный код состояния HTTP. когда ресурс доступен, но недоступен из-за разрешений


Я пошел с 403 на существующий ресурс, если это не ваше, чтобы не очищать кеш, и 404 на всех несуществующих ресурсах, чтобы сказать клиентам, чтобы они стерли эти данные.

Как указывалось ранее, следует использовать 401 вместо 403. 404 можно вернуть, если вы просто хотите сказать «извините, ресурс не найден». Однако, если вы хотите сказать «ресурс был здесь, но его больше нет и больше никогда не будет» (это, похоже, так в вашей ситуации), вы можете вернуть 410:

410 ушел

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


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

  • GET /api/documents/1 - 401 Пользователь не вошел в систему
  • GET /api/documents/1 - 200 У пользователя есть разрешение
  • GET /api/documents/1 - 401 У пользователя нет разрешения
  • DELETE /api/documents/1 - 204 У пользователя есть разрешение
  • DELETE /api/documents/1 - 403 У пользователя нет разрешения
  • GET /api/documents/2 - 404 Разрешение пользователя не актуально, ресурс не существует
  • DELETE /api/documents/2 - 404 Разрешение пользователя не актуально, ресурс не существует
  • DELETE /api/documents/1 - 410 У пользователя есть разрешение, ресурс уже удален
  • DELETE /api/documents/1 - 401 У пользователя нет разрешения, ресурс уже удален

Для последнего вы можете вернуть 401, если не хотите, чтобы неавторизованный пользователь знал, что существует ресурс, который уже был удален. Если вам все равно, вы можете вернуть 410. Это вам решать.

Мне не нравится переход с 403 на 404 на чужих ресурсах.

Совершенно нормально возвращать разные коды состояния в зависимости от ситуации.

Надеюсь, это вам немного поможет.

person Tim    schedule 06.05.2014
comment
Очень хороший момент, но я должен не согласиться, имея дело с 401 и 403. Как указано в ответе, на который вы указали, в дикой природе 401 обычно запрашивает имя пользователя / пароль, а 403 означает отказ в разрешении. Я использую токены Oauth2 для доступа, и 401 скажет клиенту убить токен и выйти из системы (например, в случае его истечения или изменения пароля). Я интерпретировал это таким же образом, поэтому мне пришлось бы не согласиться с предложенной вами реализацией. - person Cleric; 06.05.2014
comment
Достаточно справедливо, однако в нем также говорится, что 403 is for a page where authenticating won't change anything. в вашем случае аутентификация будет иметь значение, поэтому я не думаю, что вам следует использовать 403 - person Tim; 06.05.2014
comment
Это конкретное предложение не давало мне уснуть по ночам, к тому же я участвовал во многих обсуждениях в офисе. Но это будет означать, что даже если вы войдете в систему как суперпользователь, ничего не изменится. Итак, я пришел, чтобы интерпретировать это как 403 - is for page where the same authentication won't change anything, в моем случае успешно войти в систему и получить новый токен, но с тем же client_id / user / scope - person Cleric; 06.05.2014
comment
Может, вы неправильно поняли это предложение? Он не говорит ..where the same authentication won't change anything, но говорит, что 403 означает, что любая аутентификация ничего не изменит - person Tim; 06.05.2014
comment
На самом деле об этом не говорится. Как я уже сказал, я так истолковал это. Как и ответ, на который вы ссылались, а также, как он указал в дикой природе, что, я думаю, означает стандарт де-факто, что является обычным делом, связанным с HTTP, и я не хочу бороться с множеством распространенных реализаций. Насколько я знаю, 401 обычно сообщает, например, приложению на телефоне, что пользователя следует перенаправить на страницу входа. Если ресурс меняет владельца во время простоя приложения, а пользователь позже пытается удалить его, это приведет к выходу пользователя из системы, даже если его / ее токен действителен для нормального использования. - person Cleric; 06.05.2014
comment
Хорошо, в этом случае это я неправильно прочитал ;-) В любом случае, я надеюсь, что это прояснило некоторые вещи, так что вы можете работать отсюда - person Tim; 06.05.2014
comment
Спасибо за идеи :) - person Cleric; 06.05.2014
comment
@Cleric, если ваши проблемы решены, вы не возражаете принять любой ответ? - person Tim; 28.10.2014
comment
В конце концов, мы решили реализовать 410 в качестве статуса отказа от всей версии api, поскольку это верно в том смысле, что ресурс никогда больше не будет доступен. 404 прагматично сохранился как код для уже удаленного ресурса. - person Cleric; 28.10.2014
comment
если ресурс существует и пользователь не авторизован для удаления этого ресурса, в спецификации http говорится, что ему также разрешено возвращать 404 :-) Нет необходимости для 401/403. цитата: ... Этот код состояния обычно используется, когда сервер не хочет раскрывать, почему запрос был отклонен ... - person Pascal; 12.06.2017
comment
401 следует использовать только в случае сбоя аутентификации во время запроса. Поэтому, если вы аутентифицированы, но запрашиваете чужой ресурс, 401 будет вводить в заблуждение. Например, кто-то может реализовать клиент, чтобы 401 перенаправлял на страницу входа. Однако 403 (или скрытие 404) подразумевает, что вы можете продолжить выполнение других запросов без повторной авторизации. - person Guney Ozsan; 18.05.2020

Код ответа на недопустимый вызов удаления зависит от того, в чем заключается сбой. В ваших случаях я бы пошел с:

  • DELETE /api/documents/1 - Users has permission
    • 204 No Content
  • DELETE /api/documents/2 - Users permission irrelevant, resource does not exist
    • 404 Not Found
  • DELETE /api/documents/1 - Users has permission, resource already deleted
    • 410 Gone
  • DELETE /api/documents/1 - Users does not have permission, resource already deleted
    • 403 Forbidden

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

Что касается _9 _ / _ 10_, 401 означает «вы еще не вошли в систему». 403 - это «вы вошли в систему, и у вас нет разрешения делать то, что вы хотите». Я не вижу ничего необычного в использовании вами этих кодов.

Сказав все это, я чувствую, что как-то неправильно истолковываю вопрос.

person Eric Stein    schedule 06.05.2014

Мне не нравится идея о том, что 404 представляет собой неудачное удаление, когда ресурс не может быть найден (или для размещения или патча в этом отношении). Довольно часто возникают проблемы с DNS и проблемы с маршрутизацией на основе параметров, которые приводят к 404, если фактический сайт не может быть найден. Введение такой двусмысленности может сделать диагностику простых проблем действительно и излишне сложной. Я думаю, что 410 Gone - лучший выбор для представления ресурса, который не найден, когда дело доходит до API.

person Marc Ziss    schedule 12.05.2017
comment
как Gone ('целевой ресурс больше не доступен на исходном сервере') лучше, чем Not Found ('Сервер не нашел ничего, соответствующего Request-URI' ) когда ресурс был не найден и вообще не известен? Кроме того, «СЛЕДУЕТ использовать код состояния 410 (Gone), если сервер знает (...), что старый ресурс постоянно недоступен». Как RFC 7231, так и здравый смысл говорят, что Gone означает, что мы уверены, что что-то присутствовало в прошлом. То, что вы предлагаете, не только неверно в свете RFC 7231, но и, IMVHO, просто абсурдно. - person ; 01.11.2017