Ні в специфікаціях W3C, ні в неофіційних правилах REST немає жодного правила, яке говорить про те, що PUT
необхідно використовувати ту саму схему / модель, що і відповідна GET
.
Приємно, якщо вони схожі , але незвично PUT
робити речі дещо інакше. Наприклад, я бачив безліч API, які включають якийсь ідентифікатор у вміст, повернутий GET
для зручності. Але при PUT
значенні a цей ідентифікатор визначається виключно URI і не має значення у змісті. Будь-який ідентифікатор, знайдений в тілі, буде мовчки ігноруватися.
REST та Інтернет взагалі сильно пов'язані з Принципом надійності : "Будьте консервативні у тому, що ви робите [надсилаєте], будьте ліберальні у тому, що приймаєте". Якщо ви погоджуєтесь з цим по-філософськи, то рішення очевидно: ігноруйте недійсні дані в PUT
запитах. Це стосується як незмінних даних, як у вашому прикладі, так і фактичних дурниць, наприклад, невідомих полів.
PATCH
потенційно інший варіант, але його не слід реалізовувати, PATCH
якщо ви насправді не підтримуєте часткові оновлення. PATCH
означає лише оновлення конкретних атрибутів, які я включаю до вмісту ; це не означає замінити всю сутність, але виключити деякі конкретні поля . Те, про що ви насправді говорите, насправді не є частковим оновленням, це повне оновлення, idempotent і все, це лише та частина ресурсу, яка доступна лише для читання.
Приємно зробити, якщо ви виберете цей варіант, було б відправити назад у відповідь 200 (ОК) з фактично оновленим об'єктом , щоб клієнти могли чітко бачити, що поля лише для читання не були оновлені.
Звичайно, є деякі люди, які думають інакше - що при спробі оновити частину ресурсу, доступного лише для читання, має бути помилкою. Для цього є певне обґрунтування, насамперед виходячи з того, що ви обов'язково повернете помилку, якби весь ресурс був лише для читання, а користувач намагався його оновити. Це, безумовно, суперечить принципу надійності, але ви можете вважати, що це більше "самодокументування" для користувачів вашого API.
Для цього є дві конвенції, обидві відповідають вашим оригінальним ідеям, але я розширю їх. Перший - забороняти появі полів для читання у вмісті та повертати HTTP 400 (поганий запит), якщо вони є. API такого типу також повинні повертати HTTP 400, якщо є інші нерозпізнані / непридатні поля. Друга - вимагати, щоб поля для читання були ідентичними поточному вмісту, і повернути 409 (конфлікт), якщо значення не збігаються.
Мені дуже не подобається перевірка рівності з 409, оскільки це незмінно вимагає від клієнта зробити а GET
, щоб отримати поточні дані, перш ніж мати можливість зробити це PUT
. Це просто не приємно і, мабуть, десь десь призведе до низької продуктивності. Я також дійсно не як 403 (Forbidden) для цього , оскільки це означає , що весь ресурс захищений, а не тільки його частину. Отже, на мою думку, якщо ви абсолютно зобов’язані перевірити, замість того, щоб дотримуватися принципу надійності, підтвердіть всі свої запити та поверніть 400 для будь-яких, які мають додаткові або незаписані поля.
Переконайтеся, що ваш 400/409 / що містить інформацію про конкретну проблему та як її усунути.
Обидва ці підходи справедливі, але я віддаю перевагу колишньому у відповідності з принципом надійності. Якщо ви коли-небудь відчували роботу з великим API REST, ви оціните цінність зворотної сумісності. Якщо ви коли-небудь вирішите видалити існуюче поле або зробити його лише для читання, це зміни, сумісні з зворотним ходом, якщо сервер просто ігнорує ці поля, а старі клієнти все ще працюватимуть. Однак якщо ви будете проводити сувору перевірку вмісту, він вже не сумісний із зворотним процесом, і старі клієнти перестануть працювати. Перший, як правило, означає менше роботи як для технічного обслуговування API, так і для його клієнтів.