Содержимое
Срочно в номер! Мы все неправильно понимали, как работают методы HTTP! Всегда ведь всем говорят, что REST строится вокруг методов HTTP, а они соответствуют операциям CRUD: POST — это Create, GET — Read, PUT — Update, DELETE — Delete. Но не всё так просто. Есть документ с объяснением семантики HTTP — RFC 7231, 'HTTP/1.1 Semantics and Content', датируется 2014 годом, за авторством самого Роя Филдинга (и обновлённый в 2022 как RFC 9110) Там всё написано, из первых уст, так сказать. Понятнее всего с GET — это действительно запрос получения ресурса. Создание ресурса — это PUT: 'The PUT method requests that the state of the target resource be created or replaced with the state defined by the representation enclosed in the request message payload.' То есть PUT может и изменять ресурс, и создавать его. Главное — в PUT создается или изменяется ресурс по конкретному адресу (URI). Понятно, что это не сработает, если мы включаем в URI идентификатор, который выдает сервер (его и знать может только сервер). Но мы, например, можем положить через PUT оценку конкретным пользователем товара или статьи: тогда первый PUT создаст оценку, последующие её поменяют, но доступна она всегда будет по одному и тому же URI. В этом примере понятно, почему PUT небезопасный: кроме самой оценки конкретного пользователя ещё поменяется и общая оценка товара (и б-г знает что ещё — может быть, место в поисковой выдаче, а может этот товар попадет на главную, и т.п.). DELETE — это не совсем удаление. Это скорее отключение ресурса — по этому URI он больше не будет доступен. Что там внутри сервера при этом произойдет — только его дело. Может быть, на самом деле всё удалится. Может быть, пометится как удаленный. Может быть, отправится в архив и появится по новому адресу (поэтому DELETE тоже небезопасная операция). В RFC сказано, что DELETE достаточно редкая операция, и может применяться к ресурсам, созданным при помощи PUT. Могут быть интересные истории, например с ресурсом, указывающим на "последнюю версию статьи". Если сказать ему DELETE — что должно произойти? Вся статья удалиться, или удалиться последняя версия, и на этом же URI должна восстановиться предыдущая версия?.. Возникает неоднозначность семантики. И самое сложное — POST. Это вовсе не создание ресурса, как мы всегда думали. Это, вообще говоря, просто семантическая дыра: 'The POST method requests that the target resource process the representation enclosed in the request according to the resource's own specific semantics.' То есть, как хотите, так и понимайте. Единственный смысл — мы хотим что-то сказать серверу, вот как. А дальше сервер уже будет решать, в соответствии с "собственной специфической семантикой ресурса". Это может быть: — передача блока данных для обработки (не факт, что что-то тут создается!); — создание нового ресурса, у которого ещё нет идентификатора и URI (обратите внимание, URI у ресурса появляется уже позже: мы обращаемся к одному адресу — к сервису, по сути, — чтобы создать ресурс по другому адресу); — добавление данных к имеющемуся ресурсу (!!!) Мы можем через POST создать один ресурс, несколько новых ресурсов, дополнить существующий ресурс, вообще ничего не создавать. Кажется, самого Филдинга не очень заботило, строите ли вы своё API через CRUD, или нет. Его гораздо больше интересовало, чтобы ваше API было самоописательным и предлагало список действий, которые вы можете осуществить с его ресурсами. И, конечно, в его диссертации вообще не упоминаются ни POST (там только GET и HEAD из методов упоминаются), ни CRUD. В отдельном посте на эту темы он так и говорит: вся эта возня с методами просто не важна для обсуждения архитектурного стиля REST, главное — соблюдать единообразие и не делать получение данных через POST (а то кэширование и перезапросы работать не будут). Так что POST — это операция со смыслом 'this action isn’t worth standardizing', "это действие не стоит стандартизации". Как видно из поста Филдинга, в нулевые было распространено представление, что "настоящий" REST должен вообще обходиться без POST(!), видимо были сильны ассоциации с SOAP.