REST - разрешить GET ресурс / выводить разные версии - PullRequest
1 голос
/ 19 июля 2011

Для простоты, скажем, у меня есть ресурс пользователей . HTTP-вызов GET users / возвращает список ссылок для конкретных пользователей:

<users>
    <link rel='user' href='/users/user/1/'/>
    <link rel='user' href='/users/user/2/'/>
    <link rel='user' href='/users/user/3/'/>
    ....
</users>

Представление результата описано в конкретном типе носителя:

application/vnd.company.Users+xml

В нашем веб-интерфейсе мы хотим отобразить таблицу со всеми пользователями. Это означает, что мы должны иметь возможность извлекать отображаемую информацию о пользователе, такую ​​как имя, пол, друзья, ... Я хотел бы избежать необходимости отдельного запроса для каждого пользователя ( GET / users / user / x / ), чтобы получить эту информацию. Кроме того, некоторые веб-интерфейсы будут отображать только имя, в то время как другие веб-интерфейсы будут отображать имя и его / ее друзей. И так далее.

По сути, мы по-прежнему возвращаем пользователей, но с расширениями, зависящими от потребностей внешнего интерфейса.

Какой вариант вы бы выбрали? Почему?

(1) Сделать GET users / настраиваемыми с помощью параметров, чтобы настройки отображались в списке. В зависимости от настроек могут быть возвращены разные типы носителей, поскольку синтаксис одной версии / комбинации может сильно отличаться от синтаксиса другой версии / комбинации:

GET users/                            -> application/vnd.company.Users+xml
GET users/?fields=name,gender         -> application/vnd.company.Users+xml
GET users/?fields=name,gender,friends -> application/vnd.company.UsersWithFriends+xml

(2) Разные ресурсы создаются для различения разных типов носителей. Параметры по-прежнему используются для основных настроек, охватываемых типом носителя. Это дает:

GET users?fields=name                -> application/vnd.company.Users+xml
GET users?fields=name,gender         -> application/vnd.company.Users+xml
GET users_with_friends?fields=gender -> application/vnd.company.UsersWithFriends+xml

(3) То же, что и (1), но вместо параметров желаемый тип носителя устанавливается клиентом в заголовке Accept. Настраиваемые поля, охватываемые типом носителя, по-прежнему задаются с помощью параметров:

GET users/?fields=name        ACCEPT application/vnd.company.Users+xml
GET users/?fields=name,gender ACCEPT application/vnd.company.Users+xml       
GET users/?fields=name,gender ACCEPT application/vnd.company.UsersWithFriends+xml

(4) Что-то еще?

Чтобы ответить на мой собственный вопрос, я думаю, что:

  • Решение (1) очень, очень неправильно. Тип носителя не должен зависеть от параметров.
  • Решения (2) и (3) более или менее равны и соответствуют предпочтениям. Я предпочитаю (3), так как это не приведет к взрыву ресурсов, которые будут представлены. Кроме того, по сути, мы все еще возвращаемся пользователям. Единственная разница - это количество информации, отображаемой разными типами медиа, которая возвращается. Таким образом, можно утверждать, что нет реальной необходимости вводить новые ресурсы, как это сделано в (2).

Вы согласны? Что ты думаешь?

Ответы [ 2 ]

1 голос
/ 19 июля 2011

Лично я не фанат использования параметров строки запроса, чтобы позволить клиентам выбирать элементы данных, которые они хотят включить в представление. Я считаю, что это затрудняет оптимизацию сервера и загрязняет кэш многими перекрывающимися вариантами. Кроме того, вы действительно не должны пытаться использовать connect для выбора между представлениями, которые содержат разные наборы данных. Conneg действительно просто для выбора формата сериализации.

С типом носителя Hal вы можете подойти к этой проблеме немного по-другому. Рассмотрим сервис с корневым представлением, который выглядит следующим образом:

<resource rel="self" 
          href="http://example.org/userservice"
          xmlns:us="http://example.org/userservice/rels">
   <link rel="us:users" name="users" href="http://example.org/users">
   <link rel="us:userswithfriends" href="http://example.org/userswithfriends">
</resource>

Когда вы используете hal, вместо того, чтобы использовать документацию типа носителя для описания домена приложения, вы можете использовать связи ссылок. В этом случае ссылка us:users указывает на документ, который содержит список пользователей. Я знаю, что пространство имен выглядит немного странно, но на самом деле оно не используется как пространство имен XML, просто как способ создания компактного URI ( CURIE ). Когда вы изобретаете свои собственные значения rel, их необходимо указывать в форме URI, чтобы попытаться обеспечить уникальность.

Список пользователей будет выглядеть примерно так:

<resource rel="self" 
          href="http://example.org/users"
          xmlns:us="http://example.org/userservice/rels">

   <resource rel="us:user" name="1" href="/user/1">
      <name>Bob</name>
      <age>45</age>
   <resource>

   <resource rel="us:user" name="2" href="/user/2">
      <name>Fred</name>
      <age>Bill</age>
   <resource>

</resource>

и 'us: userswithfriends' указывают на другой ресурс, содержащий список пользователей, каждый из которых содержит список друзей.

<resource rel="self" 
          href="http://example.org/users"
          xmlns:us="http://example.org/userservice/rels">

   <resource rel="us:user" name="1" href="/user/1">
      <name>Bob</name>
      <resource rel="us:friend" name="1" href="/user/10">
        <name>Sheila</name>
      <resource>
      <resource rel="us:friend" name="2" href="/user/74">
        <name>Robert</name>
      <resource>
   <resource>

   <resource rel="user" name="2" href="/user/2">
      <name>Fred</name>
      <resource rel="us:friend" name="1" href="/user/14">
        <name>Bill</name>
      <resource>
      <resource rel="us:friend" name="2" href="/user/33">
        <name>Margaret</name>
      <resource>

   <resource>

</resource>

С hal это документация ваших rel (us: users, us: friend), которая описывает, какие элементы данных могут существовать в элементе ресурса. Вы можете встраивать все данные ресурса, или, скорее всего, просто подмножество данных. Если клиент хочет получить доступ к полному представлению встроенного ресурса, он может перейти по предоставленной ссылке.

1 голос
/ 19 июля 2011

(3), безусловно, лучше всего использовать строгий тип носителя, но для него потребуется специальный клиент HTTP-запросов, и он не будет доступен через открытую библиотеку URL-адресов или браузер.

Почему бы не использовать решение 1 с другим дополнительнымпараметр: имена «ожидаем» или «как».т.е.: пользователи /? fields = имя, пол & ожидаемый = application / vnd.company.Users + xml пользователи /? fields = имя, пол и ожидаемый = application / vnd.company.UsersWithFriends + xml

Это будет то же самое, что иРешение ACCEPT, но для подделки запроса не потребуется особая клиентская библиотека.Однако вам придется проанализировать параметр, чтобы обеспечить корректный вывод (в (3) также будет это требование для анализа ACCEPT)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...