4

API コンシューマに公開されていない別のメソッドを介して変更/更新する必要があるリソース プロパティを処理する最良の方法は何ですか?

例:

  1. X に使用する新しいトークンを要求します。トークンは、特定の一連のビジネス ルール/ロジックに従って生成する必要があります。

  2. 古いレートの有効期限が切れた後の通貨の為替レートのリクエスト/更新。レートは情報提供を目的としており、その後の取引で使用されます。

上記の 2 つの例では、値はリソースのプロパティであり、個別のリソースではないことに注意してください。

これらのタイプのシナリオや、API コンシューマーがプロパティの値を制御できず、新しい値を要求する必要があるその他のシナリオを処理する最善の方法は何ですか。1 つのオプションは、要求本文でその特定のプロパティを使用できるようにすることPATCHですが、実際には指定された値にプロパティを更新するのではなく、必要なロジックを実行してプロパティを更新し、更新されたリソースを返すことです。

#1 をさらに詳しく見てみましょう。

リクエスト:

GET /User/1

応答:

{
   "Id": 1,
   "Email": "myemail@gmail.com",
   "SpecialToken": "12345689"
}

API のコンシューマとして、新しい をリクエストできるようにしたいのですがSpecialToken、トークンを生成するためのビジネス ルールが見えません。

SpecialTokenREST パラダイムで新しい/更新が必要であることを API に伝えるにはどうすればよいですか?

1つの考えは、次のことです。

リクエスト:

PATCH /User/1
{
   "SpecialToken": null
}

サーバーはこのリクエストを見て、トークンを更新する必要があることを認識します。バックエンドはSpecialToken特定のアルゴリズムで を更新し、更新されたリソースを返します。

応答:

{
   "Id": 1,
   "Email": "myemail@gmail.com",
   "SpecialToken": "99999999"
}

SpecialTokenこの例は、 が resource の為替レートである例 #2 に拡張できますCurrencyTradeExchangeRateAPI のコンシューマーが直接変更できない読み取り専用の値ですが、変更/更新を要求できます。

リクエスト:

GET /CurrencyTrade/1

応答:

{
   "Id": 1,
   "PropertyOne": "Value1",
   "PropertyTwo": "Value2",
   "ExchangeRate":  1.2
}

API を使用する人は、新しい ExchangeRate を要求する方法が必要になりますが、値がどうなるかを制御することはできません。厳密にはread only property.

4

5 に答える 5

2

それには多くのアプローチがあります。/User/1/SpecialTokenリソース202 Acceptedを完全に削除することはできず、誰かが削除しようとするたびに更新されることを説明するメッセージが表示されます。 次に、DELETE、NULL 値に置き換える PUT、さらに SpecialToken または User の属性に直接 PATCH を使用してそれを行うことができます。他の誰かが言及したことにもかかわらずSpecialToken、 User リソースに値を保持することに問題はありません。クライアントは 2 つの要求を行う必要はありません。

TokenRefresher リソースへの POST である @AndyDennie によって提案されたアプローチも問題ありませんが、カスタマイズされた動作のようには感じられないため、他のアプローチをお勧めします。ドキュメントで、このリソースを削除できず、サーバーが単に更新することが明確になると、クライアントは、更新するために、標準化されたアクションでリソースを削除または null に設定できることを認識します。

実際の RESTful API では、ユーザーのハイパーメディア表現には、「リフレッシュ トークン」というラベルの付いたリンクがあり、どのような操作が行われても、URI のセマンティクスはあまり重要ではないことに注意してください。

于 2013-11-06T23:42:55.853 に答える
1

別の考えがちょうど私に起こりました。RefreshToken リソースをモデル化するのではなく、既存の特別なトークンを、このユーザーに関連付けられている RevokedTokens コレクションに単純に POST することができます (特定の時点でユーザーごとに許可される特別なトークンは 1 つだけであると仮定します)。

リクエスト:

GET /User/1
Accept: application/hal+json

応答:

200 OK
Content-Type: application/hal+json

{
   _links: {
     self: { href: "/User/1" },
     "token-revocation": { href: "/User/1/RevokedTokens" }
   },
   "Id": 1,
   "Email": "myemail@gmail.com",
   "SpecialToken": "12345689"
}

トークン取り消し関係に従い、既存の特別なトークンを POST すると、次のようになります。

リクエスト:

POST /User/1/RevokedTokens
Content-Type: text/plain

123456789

応答: 202 Accepted (または 204 No Content)

ユーザーの後続の GET では、新しい特別なトークンが割り当てられます。

リクエスト:

GET /User/1
Accept: application/hal+json

応答:

200 OK
Content-Type: application/hal+json

{
   _links: {
     self: { href: "/User/1" },
     "token-revocation": { href: "/User/1/RevokedTokens" }
   },
   "Id": 1,
   "Email": "myemail@gmail.com",
   "SpecialToken": "99999999"
}

これには、サービスをリソース (つまり、トークン リフレッシャー リソース) としてモデル化するのではなく、他のリソースに影響を与える可能性のある実際のリソース (トークン取り消しリスト) をモデル化するという利点があります。

于 2013-11-07T22:14:16.667 に答える
1

リソースの作成を検討しSpecialToken、API の消費者がPOST新しいインスタンスを取得できるようにする必要があると思います。Userどういうわけか、リソースをリソースにリンクしたいと思うでしょうSpecialToken。REST の中心的な原則の 1 つは、帯域外の情報に依存してはならないということです。そのため、それを忠実に守りたい場合は、リンクを使用する可能性を調査する必要があります。

まず、あなたが持っているものを見てみましょう:

リクエスト:

GET /User/1
Accept: application/json

応答:

200 OK
Content-Type: application/json


{
   "Id": 1,
   "Email": "myemail@gmail.com",
   "SpecialToken": "12345689"
}

SpecialTokenこの応答にはオブジェクトにプロパティが含まれていますが、この特定のオブジェクト構造を理解するようにプログラムされていないクライアントにとっては、実際には何も意味しないためですContent-Typeapplication/jsonJSON を理解するだけのクライアントは、これを他のオブジェクトと同様にオブジェクトとして受け取ります。今はそれを無視しましょう。SpecialTokenフィールドに別のリソースを使用するというアイデアを採用したとしましょう。次のようになります。

リクエスト:

GET /User/1/SpecialToken
Accept: application/json

応答:

200 OK
Content-Type: application/json

{
    "SpecialToken": "12345689"
}

を実行したためGET、理想的には、この呼び出しを行ってもリソースは変更されません。ただし、POSTメソッドは同じセマンティクスに従っていません。実際、POSTこのリソースにメッセージを発行すると、別の本文が返される可能性があります。そこで、次のことを考えてみましょう。

リクエスト:

POST /User/1/SpecialToken
Accept: application/json

応答:

200 OK
Content-Type: application/json

{
    "SpecialToken": "98654321"
}

POSTメッセージに本文が含まれていないことに注意してください。これは型にはまらないように思えるかもしれませんが、HTTP 仕様はこれを禁止しておらず、実際、W3C TAG はそれで問題ないと言っています

HTTP メッセージ本文でデータを提供しなくても POST を使用できることに注意してください。この場合、リソースは URI アドレス指定可能ですが、POST メソッドはクライアントに対して、相互作用が安全でないか副作用がある可能性があることを示します。

私にはほぼ正しいように聞こえます。POST以前、一部のサーバーで本文のないメッセージに問題があると聞いたことがありますが、個人的には問題はありませんでした。ヘッダーが適切に設定されていることを確認してContent-Lengthください。

それを念頭に置いて、これはあなたが提案していることを行うための完全に有効な方法のようです(RESTによると)。しかし、JSON が実際にはアプリケーション レベルのセマンティクスを持たないことについて少し触れたときのことを覚えていますか? つまり、クライアントが実際に を送信して最初POSTに新しい を取得するSpecialTokenには、そのリソースの URL、または少なくともそのような URL を作成する方法を知る必要があります。これは、クライアントをサーバーに結びつけるため、悪い習慣と見なされます。説明しましょう。

次のリクエストがあるとします。

POST /User/1/SpecialToken
Accept: application/json

サーバーが URL を認識しなくなった場合、/User/1/SpecialToken404 またはその他の適切なエラー メッセージが返され、クライアントが壊れている可能性があります。これを修正するには、担当するコードを変更する必要があります。これは、クライアントとサーバーが互いに独立して進化することができず、結合を導入したことを意味します。ただし、クライアントの HTTP ルーチンでヘッダーを検査できる場合、これを修正するのは比較的簡単です。その場合、メッセージへのリンクを導入できます。最初のリソースに戻りましょう。

リクエスト:

GET /User/1
Accept: application/json

応答:

200 OK
Content-Type: application/json
Link: </User/1/SpecialToken>; rel=token

{
   "Id": 1,
   "Email": "myemail@gmail.com",
   "SpecialToken": "12345689"
}

応答には、ヘッダーで指定されたリンクがあります。この小さな追加により、クライアントはリソースへのアクセス方法を知る必要がなくなりSpecialToken、リンクをたどるだけで済みます。これはすべてのカップリングの問題を処理するわけではありませんが (たとえば、登録されたリンク関係tokenではありません)、大いに役立ちます。サーバーはURL を自由に変更できるようになり、クライアントは変更しなくても動作します。SpecialToken

これは HATEOAS (Hypermedia As The Engine Of Application State の略) の小さな例です。これは基本的に、アプリケーションが物事を前もって知るのではなく、やり方を発見することを意味します。頭字語部門の誰かがこれで解雇されました。このトピックに関する食欲をそそるために、ハイパーメディアを多用する API を示すJon Moore による非常にクールな講演があります。ハイパーメディアのもう 1 つの優れた入門書は、Steve Klabnik の著書です。これで始められるはずです。

お役に立てれば!

于 2013-11-07T00:48:33.917 に答える
0

User リソース内のトークンを更新する責任を負う別のリソースはどうですか?

POST /UserTokenRefresher
{
    "User":"/User/1"
}

これにより、更新された User 表現 (新しいトークンを含む) が応答で返される可能性があります。

于 2013-11-06T22:47:45.270 に答える