Ответ 1
Как отметил @Mark Dickinson, здесь есть много вопросов, которые действительно должны быть отдельными, но я сделаю все возможное.
Иерархия против плоского дизайна
В REST нет ничего, что указывало бы, что у вас не может быть несколько параллельных иерархий (хотя я понимаю, что делать это с Rails неудобно). Имея /users/42/photos/owner
и /photos/owner/42
, содержащие один и тот же набор, отлично. Аналогично /users/42/photos/tagged
и /photos/tagged/42
могут содержать один и тот же набор. Однако вы не должны беспокоиться об URI в это время. Существует отличная статья API RESTful Hypermedia в трех простых шагах, в котором описывается, как разработать свой API. В этой статье URI определяются как последний шаг.
Кроме того, используя HATEOAS, эти различные URI должны быть открыты во время выполнения клиентом через ссылки и формы по вашему приложению.
Кэширование, когда контент отличается для разных пользователей
Если вы собираетесь обслуживать разные контенты с одного и того же URL-адреса, тогда он не будет кэшироваться. Вы можете разделить ваш сайт на два типа контента, публичный и персонализированный. Публичный контент должен быть одинаковым для всех и может быть кэширован. Персональный контент отличается для каждого пользователя, а это означает, что сумма, которую вы можете кэшировать, будет значительно уменьшена (уменьшена до нуля, используя формат URL, который вы использовали в ваших примерах).
Чтобы получить хотя бы небольшое количество кеширования на персонализированном контенте, отделите контент от пользователя, чтобы для пользователя дать вам доступ к кешу. Например, вместо /users/42
, к которому каждый может получить доступ, используйте /<UID>/users/42
, где находится идентификатор пользователя запрашивающего пользователя. например пользователь 234 будет обращаться к странице профиля для пользователя 42, используя URI /234/users/42
. Для анонимных пользователей вы можете либо удалить часть /<UID
, либо использовать для них определенный идентификатор пользователя, например /public/users/42
.
Предоставление HTML и JSON/XML из одного ресурса
Используйте заголовок Accept
. Это то, для чего оно существует.
Ограничение данных, отправленных назад
Вам не нужно делать /users
незаконный запрос. Обработка - это коллекция и возвращает список пользователей, список которых разрешен для просмотра. Например, для анонимного запроса вы можете указать пустой список (или 204 без содержимого)
<users/>
и для конкретного зарегистрированного пользователя вы можете предоставить своим друзьям.
<users>
<user id="42" href="/users/42" name="John Doe"/>
<user id="53" href="/users/53" name="Jane Doe"/>
...
<next href="/users?page=2"/>
</users>
когда этот пользователь затем GETs /users?page=2
, вы предоставите следующую страницу результатов
<users>
<user id="69" href="/users/69" name="John Smo"/>
<user id="84" href="/users/84" name="Jane Smo"/>
...
<next href="/users?page=3"/>
<prev href="/users"/>
</users>
С последней страницей результатов без ссылки next
. Чтобы добавить функцию поиска, вы просто добавляете соответствующую форму в качестве части ответа.
<users>
<user id="69" href="/users/69" name="John Smo"/>
<user id="84" href="/users/84" name="Jane Smo"/>
...
<next href="/users?page=2"/>
<prev href="/users"/>
<search href="/users" method="get">
<name cardinality="required" type="regex"/>
</search>
</users>
Результаты поиска будут разбиты на страницы, как и в списке /users
. например, поиск leet hacker
(Предполагая, что у вас есть разрешение на просмотр большого количества вредоносных хакеров в системе) создаст что-то вроде
<users>
<user id="234" href="/users/234" name="leet hacker"/>
<user id="999" href="/users/999" name="leet hacker"/>
...
<next href="/users?name=leet+hacker&page=2"/>
<search href="/users" method="get">
<name cardinality="required" type="regex"/>
</search>
</users>
однако вам, вероятно, понадобится предоставить более подробную информацию в пользовательском элементе, чтобы можно было дифференцировать литовских хакеров.
Контроллеры, предоставляющие избыточные данные
Оба приемлемы. Однако, как указано выше (по причинам кэширования), я использовал бы /<UID>/users/42
, и в этом случае вы можете перенаправить /42/users/me
на /42/users/42
.
Это также помогает с точки зрения аналитики, поскольку вы можете отдельно отслеживать, как пользователи получают доступ к своей собственной странице, от доступа пользователей к странице других пользователей, чтобы узнать, какие пользователи популярны и которые являются нарциссическими. Вы даже можете найти корреляцию между двумя:)
Расширенные права для некоторых пользователей
Предоставьте ссылки администратора и формы в соответствующем ответе. Например, доступ к деталям изображения другого пользователя может обеспечить
<image id="266" href="/photos/266" caption="leet hacker with computer"
src="http://us.123rf.com/400wm/400/400/creatista/creatista0911/creatista091100003/5827629.jpg"/>
<tagged-users>
<user id="234" href="/users/234" name="leet hacker"/>
</tagged-users>
<owner id="234" href="/users/234" name="leet hacker"/>
</image>
но для владельца изображения он может обеспечить
<image id="266" href="/photos/266" caption="leet hacker with computer"
src="http://us.123rf.com/400wm/400/400/creatista/creatista0911/creatista091100003/5827629.jpg"/>
<tagged-users>
<tagged-user id="234" href="/users/234" name="leet hacker">
<delete href="/photos/266/tagged/234" method="delete"/>
</tagged-user>
<add href="/photos/266" method="put">
<user cardinality="required" type="user-id"/>
</add>
</tagged-users>
<owner id="234" href="/users/234" name="leet hacker"/>
<delete href="/photos/266" method="delete"/>
<update href="/photos/266" method="put">
<caption cardinality="optional" type="string"/>
</update>
</image>
Обновления локализации и настроек
Используйте Accept-Language
для языка по умолчанию, но разрешите пользователю изменять язык в своих настройках.