Прошлые домены не функционирует! Используйте адрес
ARHIVACH.VC.
24 декабря 2023 г. Архивач восстановлен после серьёзной аварии. К сожалению, значительная часть сохранённых изображений и видео была потеряна.
Подробности случившегося. Мы призываем всех неравнодушных
помочь нам с восстановлением утраченного контента!
Ведь REST - это буквально о том, как ресурсу (объекту) пользователь устанавливает напрямую атрибуты. Инкапсуляция, получается, идёт прямиком в жопу.
Пример.
Есть приглашение (invitation), пользователь может его принять или отвергнуть. В каждом из этих действий подключается разная логика. Например, при приёме нужно добавить пользователя как участника ивента, на который его пригласили, и разослать всем участникам уведомление о новом участнике. А в случае отказа - уведомить пригласившего.
Эти куски логики будут инкапсулированы внутри методов Invitation.accept и Invitation.refuse.
Как это будет отражено в API?
REST:
PUT /invitiations/:id
{status: "accepted|refused"}
Чем это плохо?
Во-первых, для двух весьма разных действий имеется одна точка входа, что нарушает interface segregation principle.
Во-вторых, представим что есть функционал изменения каких-то атрибутов (например, время, место) у еще не принятого invitation. Это действие в REST будет иметь точно такой же endpoint:
PUT /invitations/:id
{time: "...", place: "..."}
А если в таком запросе будут присланы одновременно все три перечисленные поля? Тут целый ворох потенциальных проблем поднимается: вызов одним запросом нескольких действий, валидация данных для них, возможно взаимоисключающие действия.
Проблему можно решить сменой интерфейса приема-отказа на
POST /invitations/:id/acceptation
POST /invitations/:id/refusal
как будто мы не действие выполняем, а создаем ресурс. Правда REST подразумевает что такой ресурс будет существовать в какой-то истории, и мы сможем посмотреть список всех приемов и отказов данного приглашения (GET /invitations/:id/acceptations), хотя мы ожидаем только единоразовое действие, да и доступ к такому списку такой нам в принципе не нужен. Выглядит как натягивание совы на глобус ради чистоты парадигмы.
Следующий вариант решения проблемы:
PUT /invitations/:id/accept
PUT /invitations/:id/refuse
что уже есть смешением REST и RPC: добираемся до нужного приглашения по REST, а инкапсулированное действие вызываем как RPC. Напоминаю, в REST глагол - только HTTP метод, в адресе же - всё существительное, в RPC же в роут попадает глагол - метод, который мы вызываем.
Интересно какой подход выбираете вы.