web-dev-qa-db-ja.com

RESTful APIでのコマンドパターンの実装

私はHTTP APIを設計している最中です。できればRESTを可能な限りRESTfulにしたいと思っています。

機能がいくつかのリソースに広がるいくつかのアクションがあり、場合によっては元に戻す必要があります。

これはコマンドパターンのように思えますが、リソースにモデル化するにはどうすればよいですか?

このようなものを通じて作成されるDepositActionのようなXXActionという名前の新しいリソースを紹介します

POST /card/{card-id}/account/{account-id}/Deposit
AmountToDeposit=100, different parameters...

これにより、実際には新しいDepositActionが作成され、そのDo/Executeメソッドがアクティブになります。この場合、201 Created HTTPステータスを返すことは、アクションが正常に実行されたことを意味します。

後でクライアントがアクションの詳細を確認したい場合は、

GET /action/{action-id}

ここでは関係ないので、更新/ PUTはブロックする必要があります。

そして、アクションを元に戻すために、

DELETE /action/{action-id}

これにより、実際に関連オブジェクトのUndoメソッドが呼び出され、そのステータスが変更されます。

元に戻す操作が1つだけで十分だとしたら、やり直す必要はありません。

このアプローチは大丈夫ですか?

落とし穴、使用しない理由はありますか?

これはクライアントのPOVから理解できますか?

12
Mithir

紛らわしい抽象レイヤーを追加しています

APIは非常にクリーンでシンプルです。 HTTP POSTは、指定されたパラメーターで新しい預金リソースを作成します。次に、Rails実装の詳細である「アクション」のアイデアを導入してAPIのコア部分ではありません。

別の方法として、このHTTP会話を検討してください...

POST/card/{card-id}/account/{account-id}/Deposit

AmountToDeposit = 100、さまざまなパラメーター...

201作成されました

場所=/card/123/account/456/Deposit/789

次に、この操作を元に戻します(技術的には、これはバランスの取れた会計システムでは許可されませんが、なんとかです)。

削除/ card/123/account/456/Deposit/789

204内容がありません

APIコンシューマーは、Depositリソースを処理していることを知っており、そのリソースで許可されている操作を(通常はHTTPのOPTIONSを介して)判別できます。

削除操作の実装は現在「アクション」を通じて行われていますが、このシステムをC#などからHaskellに移行し、フロントエンドを維持するときに、「アクション」の二次概念が付加価値を提供し続けるという保証はありません、預金の主要な概念は確かにあります。

DELETEおよびDepositの代替をカバーするように編集

削除操作を回避しながら、預金を効果的に削除するには、次の手順を実行する必要があります(一般的なトランザクションを使用して預金と引き出しを可能にします)。

POST/card/{card-id}/account/{account-id}/Transaction

金額= -1、さまざまなパラメーター...

201作成されました

場所=/card/123/account/456/Transation/790

まったく逆の量(-100)の新しいトランザクションリソースが作成されます。これは、アカウントを0に戻し、元のトランザクションを無効にする効果があります。

あなたは次のような「ユーティリティ」エンドポイントの作成を検討するかもしれません

POST/card/{card-id}/account/{account-id}/Transaction/789/Undo <-BAD!

同じ効果を得るために。ただし、これは、動詞を導入することにより、URIを識別子としてのセマンティクスを壊します。識別子の名詞にこだわり、操作をHTTP動詞に制限することをお勧めします。そうすれば、識別子からパーマリンクを簡単に作成して、GETなどに使用できます。

13
Gary Rowe

RESTが存在する主な理由は、ネットワークエラーに対する回復力です。そのためには、すべての操作をべき等にする必要があります。

基本的なアプローチは合理的であるように見えますが、DepositActionの作成について説明する方法はべき等であるとは思えないため、修正する必要があります。 clientに重複した要求を検出するために使用される一意のIDを提供させる。したがって、作成は次のように変わります

PUT /card/{card-id}/account/{account-id}/Deposit/{action-id}
AmountToDeposit=100, different parameters...

同じURLへの別のPUTが以前と同じコンテンツで行われた場合、応答は201 createdコンテンツが同じ場合はエラー、コンテンツが異なる場合はエラー。これにより、クライアントは要求または応答が失われたかどうかを判断できないため、失敗したときに要求を再送信するだけで済みます。

リソースを書き込むだけでべき等であるため、PUTを使用する方が理にかなっていますが、POSTを使用しても問題は発生しません。

トランザクションの詳細を確認するために、クライアントは同じURLをGETします。

GET /card/{card-id}/account/{account-id}/Deposit/{action-id}

元に戻すには、削除することができます。しかし、サンプルが示唆するように実際にお金と関係がある場合は、説明責任のために代わりに「キャンセル」フラグを追加してそれをPUTすることをお勧めします(作成およびキャンセルされたトランザクションの痕跡が残っているため)。

次に、一意のIDを作成する方法を選択する必要があります。いくつかのオプションがあります。

  1. 含める必要がある交換の前半で、クライアント固有のプレフィックスを発行します。
  2. 特別なPOSTリクエストを追加して、サーバーから空の一意のIDを取得します。このリクエストはべき等である必要はありません(実際にはできない)。なぜなら、未使用のIDは本当に問題を引き起こさないからです。
  3. 単にUUIDを使用します。誰もがそれらを使用しており、MACベースのものもランダムなものも問題がないようです。
1
Jan Hudec