Нет ни правила, ни в спецификации W3C, ни в неофициальных правилах REST, которые утверждают, что PUT
необходимо использовать ту же схему / модель, что и соответствующая ей GET
.
Приятно, если они похожи , но нет ничего необычного в том, PUT
чтобы делать вещи немного по-другому. Например, я видел много API-интерфейсов, которые включают в себя некоторый идентификатор в контенте, возвращаемом символом a GET
, для удобства. Но с PUT
, этот идентификатор определяется исключительно URI и не имеет значения в контенте. Любой идентификатор, найденный в теле, будет игнорироваться.
REST и сеть в целом тесно связаны с принципом надежности : «Будьте консервативны в том, что вы делаете [отправляйте], будьте либеральными в том, что вы принимаете». Если вы философски согласны с этим, то решение очевидно: игнорируйте любые неверные данные в PUT
запросах. Это относится как к неизменным данным, как в вашем примере, так и к действительной бессмыслице, например, к неизвестным полям.
PATCH
это потенциально другой вариант, но вы не должны реализовывать, PATCH
если вы не собираетесь поддерживать частичные обновления. PATCH
означает обновление только определенных атрибутов, которые я включаю в контент ; это не означает замену всей сущности, но исключает некоторые конкретные поля . То, о чем вы на самом деле говорите, это не частичное обновление, это полное обновление, идемпотент и все такое, просто эта часть ресурса доступна только для чтения.
Хорошо, если вы выберете эту опцию, то отправите обратно 200 (ОК) с действительным обновленным объектом в ответе, чтобы клиенты могли четко видеть, что поля только для чтения не были обновлены.
Есть, конечно, некоторые люди, которые думают иначе - попытка обновить доступную только для чтения часть ресурса должна быть ошибкой. Для этого есть некоторые основания, прежде всего на том основании, что вы обязательно вернете ошибку, если весь ресурс доступен только для чтения и пользователь попытается его обновить. Это определенно идет вразрез с принципом надежности, но вы можете считать его более «самодокументированным» для пользователей вашего API.
Для этого есть два соглашения, каждое из которых соответствует вашим оригинальным идеям, но я остановлюсь на них. Во-первых, нужно запретить отображение в содержимом доступных только для чтения полей и вернуть HTTP 400 (неверный запрос), если они это делают. API такого рода также должны возвращать HTTP 400, если есть какие-либо другие нераспознанные / неиспользуемые поля. Второе - требовать, чтобы доступные только для чтения поля были идентичны текущему контенту, и возвращать 409 (Конфликт), если значения не совпадают.
Мне действительно не нравится проверка на равенство с 409, потому что она неизменно требует, чтобы клиент сделал a GET
, чтобы получить текущие данные, прежде чем он сможет сделать a PUT
. Это просто нехорошо и, вероятно, приведет к снижению производительности, для кого-то, где-нибудь. Мне также действительно не нравится 403 (Запрещено) для этого, поскольку это означает, что защищен весь ресурс, а не только его часть. Поэтому я считаю, что если вам абсолютно необходимо выполнить проверку вместо того, чтобы следовать принципу надежности, проверьте все ваши запросы и верните 400 для всех, которые имеют дополнительные или недоступные для записи поля.
Убедитесь, что ваш 400/409 / что-либо включает в себя информацию о том, что конкретная проблема и как ее исправить.
Оба эти подхода верны, но я предпочитаю первый в соответствии с принципом надежности. Если вам когда-либо приходилось работать с большим API REST, вы по достоинству оцените ценность обратной совместимости. Если вы когда-нибудь решите удалить существующее поле или сделать его доступным только для чтения, это будет обратно совместимым изменением, если сервер просто игнорирует эти поля, а старые клиенты все равно будут работать. Однако, если вы выполните строгую проверку содержимого, оно больше не будет обратно совместимым, и старые клиенты перестанут работать. Первый, как правило, означает меньше работы как для сопровождающего API, так и для его клиентов.