1

簡単にするために、リソースusersがあるとします。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ユーザー/カスタマイズ可能にします。あるバージョン/組み合わせの構文は別のバージョン/組み合わせの構文とは大きく異なる可能性があるため、カスタマイズによっては、異なるメディア タイプが返される場合があります。

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) で行ったような新しいリソースを導入する必要はないと主張する人もいるかもしれません。

同意しますか?どう思いますか?

4

2 に答える 2

1

Personally, I'm not a fan of using query string parameters to allow clients to pick the data elements they wish to include in a representation. I find it makes it hard to optimize the server and it pollutes the cache with many overlapping variants. Also, you really shouldn't try and use conneg to select between representations that contain different sets of data. Conneg is really just for selecting the serialization format.

With the Hal media type you can approach this problem a bit differently. Consider a service with a root representation that looks like:

<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>

When you use hal, instead of using the media type documentation to describe your application domain, you can use link relations. In this case, the us:users link points to a document that contains a list of users. I know the namespace stuff looks a bit wierd, but it is not really being used as an XML namespace, just as way of making a Compact URI (CURIE). When you invent your own rel values, they need to be specified in the form of a URI to try and ensure uniqueness.

The list of users would look something like:

<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>

and 'us:userswithfriends' points to a different resource that contains the list of users with each user containing a list of friends.

<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>

With hal it is the documentation of your rels (us:users, us:friend) that decribes what data elements are allowed to exist in the resource element. You are free to embed all of the data of the resource, or more likely just a subset of the data. If the client wants to access a completely representation of the embedded resource then it can follow the provided link.

于 2011-07-19T13:27:36.393 に答える
1

(3) is surely the best using strict Media Type, but would require specific HTTP Request client and won't be accessible through basic URL open library or browser.

Why not using solution 1 with another extra parameter : names "expect" or "as". ie: users/?fields=name,gender&expect=application/vnd.company.Users+xml users/?fields=name,gender&expect=application/vnd.company.UsersWithFriends+xml

This would be the same as ACCEPT solution but won't need very custom client library to forge the request. However you'll have to parse the parameter to provide correct output (the (3) would also have this requirement for parsing the ACCEPT)

于 2011-07-19T11:30:12.567 に答える