Системный сдвиг – Telegram
Системный сдвиг
10.1K subscribers
270 photos
8 videos
20 files
272 links
Авторский канал Юрия Куприянова. Обучаю системных аналитиков. Пишу про нетривиальные темы в анализе, проектировании систем, управлении и обучении.

Программный директор WAW, член ПК Flow, ЛАФ.

Контакты: @YuryKupriyanov

Курсы: https://systems.education
Download Telegram
Мы всё неправильно понимаем про HTTP метод PATCH.

Иногда читать стандарты очень увлекательно — становится понятно, что люди имели в виду на самом деле. Читать книги и статьи опаснее — там уже личные интерпретации, кто как понял. Почти во всех примерах, что мне встречались, тело запроса PATCH описано, как набор новых значений полей в JSON — с оговоркой, что в случае PUT мы должны были бы передать все поля, а не только изменившиеся, а в случае PATCH — только изменившиеся.

Но в стандарте — RFC 5789 — написано совсем другое! В запросе PATCH должен передаваться набор изменений, применяемых к ресурсу, в формате "патч-документа". Что это за формат — зависит от медиа-типа ресурса. В реестре медиа-типов IANA есть, например, типы патч-документов для json: application/json-patch+json и application/merge-patch+json; и тип для XML: xml-patch+xml (ну ещё несколько специфических).

Документ JSON-patch [RFC 6902] выглядит именно как набор операций, вносящих изменения в JSON:

   [
{ "op": "test", "path": "/a/b/c", "value": "foo" },
{ "op": "remove", "path": "/a/b/c" },
{ "op": "add", "path": "/a/b/c", "value": [ "foo", "bar" ] },
{ "op": "replace", "path": "/a/b/c", "value": 42 },
{ "op": "move", "from": "/a/b/c", "path": "/a/b/d" },
{ "op": "copy", "from": "/a/b/d", "path": "/a/b/e" }
]


op — это, понятно, название операции, вот какие операции могут быть:

add — добавить элемент в массив или свойство в объект;
remove — удалить свойство объекта или элемент массива;
replace — соответственно, заменить (как последовательное применения remove и add);
move — переместить значение из одного места (пути) в другой (тоже как remove и add, но у add будет другой путь);
copy — скопировать значение и вставить в другое место;
test — проверить значение по указанному адресу на соответствие (без масок или регулярных выражений, просто на совпадение).

Понятно, что неидемпотентным PATCH делает именно операция add — если будем применять её несколько раз к массиву, добавится много элементов вместо одного.

То, как обычно описывают формат применения PATCH — больше похоже на merge-patch+json: там мы действительно передаем только изменившиеся свойства, и null для тех свойств, которые хотим удалить.

В любом случае, тип медиа не должен быть просто application/json — по стандарту (а точнее — по errata к стандарту, списку исправлений), сервер вообще должен возвращать ошибку 415, если в запросе PATCH приходит тот же медиа тип, что у ресурса — то есть, не json-patch, просто json. Это чтобы избежать неоднозначности интерпретации. А в каких форматах сервер готов принимать патч-документ — он должен сам сказать в ответе на запрос OPTIONS: Accept-Patch: application/prs.example.patch+json, application/json-patch+json, application/merge-patch+json.

Вот так PATCH должен работать на самом деле. Ясно, что он так практически никогда не работает, так что можете этими знаниями блеснуть на собеседовании, разве что. И то — будьте осторожны, а то интервьюер примет вас за зануду-теоретика, выучившего стандарты, но далекого от практики. А на практике ни один фронтендер не будет вам конструировать сложный патч-документ, когда можно передать просто набор изменившихся полей. Ну, или пока дело не дойдет до какого-то очень сложного по структуре, со многими уровнями вложенности объекта.
👍26🔥154
По сети, говорят, ходит флешмоб про 20 книг, которые до сих пор с вами или сильно повлияли на вас: без объяснения, только обложки.

Вот мои 20 (это те, что "по специальности"). Удивительно тут, конечно, что по системному анализу и управлению требованиями книг тут не так много — даже не понятно, откуда я этого всего нахватался.
6