Binder
とDoc
が独立していることを意味する関連付け関係を持つ2つのリソースDoc
とBinder
があると仮定しましょう。 Doc
はBinder
に属する場合と属さない場合があり、Binder
は空の場合があります。
ユーザーがDoc
sのコレクションを送信できるREST APIを設計する場合は、IN A SINGLE REQUEST、次のように:
{
"docs": [
{"doc_number": 1, "binder": 1},
{"doc_number": 5, "binder": 8},
{"doc_number": 6, "binder": 3}
]
}
docs
の各ドキュメントに対して、
doc
が存在する場合は、Binder
に割り当てますdoc
が存在しない場合は、作成してから割り当てる私はこれがどのように実装されるべきかについて本当に混乱しています:
/binders/docs
?POSTまたはPATCHメソッドを使用してこれを処理できると思うのは、彼らは通常このために設計しているからです。
POST
メソッドの使用は通常、リストリソースで使用される場合に要素を追加するために使用されますが、このメソッドのいくつかのアクションをサポートすることもできます。この回答を参照してください: RESTリソースコレクションを更新する方法 。入力のさまざまな表現形式をサポートすることもできます(配列または単一の要素に対応する場合)。
この場合、更新を説明するためにフォーマットを定義する必要はありません。
PATCH
methodを使用することも適切です。これは、対応するリクエストが部分的な更新に対応しているためです。 RFC5789によると( http://tools.ietf.org/html/rfc5789 ):
Hypertext Transfer Protocol(HTTP)を拡張するいくつかのアプリケーションでは、部分的なリソース変更を行う機能が必要です。既存のHTTP PUTメソッドは、ドキュメントの完全な置換のみを許可します。この提案は、既存のHTTPリソースを変更する新しいHTTPメソッドPATCHを追加します。
この場合、部分的な更新を記述するためにフォーマットを定義する必要があります。
この場合、POST
とPATCH
は非常に似ていると思います。これは、各要素に対して行う操作を実際に記述する必要がないためです。送信する表現の形式に依存すると言うでしょう。
PUT
のケースは少し明確ではありません。実際、メソッドPUT
を使用するときは、リスト全体を提供する必要があります。実際のところ、リクエストで提供される表現は、リストリソースの表現に置き換わります。
リソースパスに関して2つのオプションがあります。
この場合、リクエストで提供する表現でバインダーとドキュメントのリンクを明示的に提供する必要があります。
この/docs
のサンプルルートを次に示します。
そのようなアプローチの内容は、メソッドPOST
の場合です。
[
{ "doc_number": 1, "binder": 4, (other fields in the case of creation) },
{ "doc_number": 2, "binder": 4, (other fields in the case of creation) },
{ "doc_number": 3, "binder": 5, (other fields in the case of creation) },
(...)
]
さらに、サブルートを活用してドキュメントとバインダー間のリンクを記述することも検討できます。ドキュメントとバインダーの関連付けに関するヒントは、リクエストコンテンツ内で指定する必要はありません。
この/binder/{binderId}/docs
のサンプルルートを次に示します。この場合、メソッドPOST
またはPATCH
を使用してドキュメントのリストを送信すると、ドキュメントが存在しない場合、ドキュメントを作成した後、ドキュメントに識別子binderId
を添付します。
そのようなアプローチの内容は、メソッドPOST
の場合です。
[
{ "doc_number": 1, (other fields in the case of creation) },
{ "doc_number": 2, (other fields in the case of creation) },
{ "doc_number": 3, (other fields in the case of creation) },
(...)
]
応答に関しては、応答のレベルと返すエラーを定義するのはあなた次第です。ステータスレベル(グローバルレベル)とペイロードレベル(シンナーレベル)の2つのレベルがあります。また、リクエストに対応するすべての挿入/更新がアトミックである必要があるかどうかを定義するのはあなた次第です。
この場合、HTTPステータスを活用できます。すべてがうまくいけば、ステータスは200
になります。そうでない場合、提供されたデータが正しくない場合(たとえば、バインダーIDが無効)またはその他の場合、400
などの別のステータス。
この場合、ステータス200
が返され、何が行われ、最終的にエラーが発生するかを記述するのは応答表現次第です。 ElasticSearchの一括更新用のREST APIにはエンドポイントがあります。これにより、このレベルでいくつかのアイデアが得られます: http://www.elasticsearch.org/guide/en/elasticsearch/guide/current/bulk.html 。
非同期処理を実装して、提供されたデータを処理することもできます。この場合、HTTPステータスの戻り値は202
になります。クライアントは、何が起こるかを見るために追加のリソースを引き出す必要があります。
終了する前に、OData仕様がnavigation linksという名前の機能を持つエンティティ間の関係に関する問題に対処していることにも注目したいと思います。おそらくあなたはこれを見ることができます;-)
次のリンクも役立ちます: https://templth.wordpress.com/2014/12/15/designing-a-web-api/ 。
お役に立てばと思います、ティエリー
おそらく、複数のリソースを更新および作成する単一のリクエストがべき等である可能性は低いため、POSTまたはPATCHを使用する必要があります。
PATCH /docs
を実行することは間違いなく有効なオプションです。特定のシナリオでは、標準のパッチ形式の使用が難しい場合があります。これについてはわかりません。
200を使用できます。 207-マルチステータス も使用できます。
これはRESTfulな方法で実行できます。私の意見では、キーは、更新/作成する一連のドキュメントを受け入れるように設計されたリソースを持つことです。
PATCHメソッドを使用する場合、操作はアトミックであると考えられます。つまり、207ステータスコードを使用せずに、応答本文で成功と失敗を報告します。 POST操作を使用する場合、207アプローチが実行可能です。どの操作が成功し、どの操作が失敗したかを通信するための独自の応答本文を設計する必要があります。標準化されたものを知りません。
PUTing
PUT /binders/{id}/docs
単一のドキュメントを作成または更新し、バインダーに関連付けます
例えば。:
PUT /binders/1/docs HTTP/1.1
{
"docNumber" : 1
}
PATCHing
PATCH /docs
存在しない場合はドキュメントを作成し、バインダーに関連付けます
例えば。:
PATCH /docs HTTP/1.1
[
{ "op" : "add", "path" : "/binder/1/docs", "value" : { "doc_number" : 1 } },
{ "op" : "add", "path" : "/binder/8/docs", "value" : { "doc_number" : 8 } },
{ "op" : "add", "path" : "/binder/3/docs", "value" : { "doc_number" : 6 } }
]
後で追加の洞察を含めますが、それまでの間は、 RFC 5789 、 RFC 6902 、William Durand's Please。Don 't Patch Like a Idiot ブログエントリ。
私が取り組んだプロジェクトでは、「バッチ」リクエストと呼ばれるものを実装することでこの問題を解決しました。次の形式でjsonを受け入れたパス/batch
を定義しました。
[
{
path: '/docs',
method: 'post',
body: {
doc_number: 1,
binder: 1
}
},
{
path: '/docs',
method: 'post',
body: {
doc_number: 5,
binder: 8
}
},
{
path: '/docs',
method: 'post',
body: {
doc_number: 6,
binder: 3
}
},
]
応答のステータスコードは207(マルチステータス)で、次のようになります。
[
{
path: '/docs',
method: 'post',
body: {
doc_number: 1,
binder: 1
}
status: 200
},
{
path: '/docs',
method: 'post',
body: {
error: {
msg: 'A document with doc_number 5 already exists'
...
}
},
status: 409
},
{
path: '/docs',
method: 'post',
body: {
doc_number: 6,
binder: 3
},
status: 200
},
]
この構造にヘッダーのサポートを追加することもできます。バッチ内のリクエスト間で使用する変数であることが証明された有用なものを実装しました。つまり、あるリクエストからのレスポンスを別のリクエストへの入力として使用できます。
FacebookとGoogleには同様の実装があります。
https://developers.google.com/gmail/api/guides/batch
https://developers.facebook.com/docs/graph-api/making-multiple-requests
同じ呼び出しでリソースを作成または更新する場合は、場合に応じてPOSTまたはPUTを使用します。文書が既に存在する場合、文書全体を次のようにしますか?
代替1の動作が必要な場合はPOSTを使用し、代替2の動作が必要な場合はPUTを使用する必要があります。
http://restcookbook.com/HTTP%20Methods/put-vs-post/
人々がすでに提案したように、PATCHに行くこともできますが、APIをシンプルに保ち、不要な場合は余分な動詞を使用しないことを好みます。