1つのリクエストで複数のアイテムを作成するRESTfulな方法


122

注文を収集する小さなクライアントサーバープログラムに取り組んでいます。これを「REST(ful)」にしたい。

私がしたいのは:

すべての注文ライン(製品と数量)を収集し、完全な注文をサーバーに送信します

現在、これを行うには2つのオプションがあります。

  1. 各注文明細をサーバーに送信します:POST qtyおよびproduct_id

サーバーへのリクエストの数を制限したいので、実際にはこれをしたくありません。オプション2です。

  1. すべてのオーダーラインを収集して、一度にサーバーに送信します。

オプション2を実装するにはどうすればよいですか?私が持っているいくつかのアイデアは次のとおりです。JSONオブジェクトですべてのオーダーラインをラップし、これをサーバーに送信するか、配列を使用してオーダーラインをポストします。

オプション2を実装するのは良いアイデアですか、それとも良い方法ですか?

良い習慣とは何ですか?

rest  post 

回答:


74

これに取り組む別の正しい方法は、リソースのコレクションを表す別のリソースを作成することだと思います。たとえば、エンドポイントが/api/sheep/{id}あり、POSTを実行/api/sheepしてシープリソースを作成できるとします。

さて、一括作成をサポートしたい場合は、新しいflockリソースを検討する必要があります/api/flock(または/api/<your-resource>-collection、より適切な名前がない場合)。ことを覚えておいてくださいリソースは、データベースやアプリケーションのモデルにマッピングする必要はありません。これはよくある誤解です。

リソースは、データとは関係のない、より高いレベルの表現です。リソースを操作すると、ユーザーへのアラートの起動、他の関連データの更新、長期間有効なプロセスの開始など、重大な副作用が発生する可能性があります。たとえば、ファイルシステムやunix psコマンドをREST APIとしてマッピングすることもできます。

リソースを操作することは、副作用として他のいくつかのエンティティを作成することを意味することもあると想定するのは安全だと思います。


私はこれに同意します。リソースのコレクションの概念を抽象化し、それをリソースのように扱う必要があります。あなたはこのなどの操作をやって起動したい場合は、今後もあなたに多くの柔軟性を提供します
villy393

これが正しいアプローチです。これはPOSTコレクション要求を壊しません。以来、単一のエンティティを投稿するために使用されます。「個別のバルクエンティティ」を使用してバルクリクエストを送信するのが正しい方法です。
ソーター2016年

2
羊と群れを使ってAPIエンドポイントを命名するのが好きです!ある程度抽象化されていると、聖書の参照がほとんどあります。「私にはこの折りたたみではない他の羊がいます。私も一緒に連れて行かなければならないので、彼らは私の声を聞くでしょう。ヨハネ10:16。
エフゲニー

1
興味深いことに、単一のリソースを作成する場合は、URLで(コレクションの)複数形を使用することをお勧めします。たとえば、POSTを/ api / booksに送信して本を作成します。しかし、(jsonとして1回のリクエストで)100冊の本を作成する場合、100冊の本のコレクションを投稿するURLはどれですか。それが落ち着きのなさが始まる場所です。
code4kix 2018年

@あなたが使用することができcode4kix /api/book-group/api/book-collectionまたは類似した何か。
ミゲルコバイン

46

多くのシステムでは一括操作(バッチ作成など)は必須ですが、RESTfulアーキテクチャスタイルでは正式に対処されていません。

あなたが提案したようにコレクションをPOSTすることは基本的には機能することがわかりましたが、そのような要求に応じて失敗を報告する必要がある場合に問題が発生します。このような問題は、さまざまな原因で複数の障害が発生した場合、またはサーバーがトランザクションをサポートしていない場合に悪化します。たとえば、サービスプロバイダーが(WANではなく)LAN上にある場合やデータが比較的小さい場合など、パフォーマンスに問題がない場合は、100のPOST要求をサーバーに送信することをお勧めします。シンプルに保ち、個別のリクエストから始め、パフォーマンスの問題がある場合は最適化を試みます。


3
バッチ処理の場合のエラーの解決策を自分で見つけましたか?モバイル接続で100件の投稿リクエストを送信して、ページの継ぎ目を悪いアイデアのように表示する。
Thomas Ahle、2011

エラーを配列に追加し、ユーザーを419 Conflictエラーページにルーティングし(そしてそのエラーをクライアントに返します)、エラーの配列を表示します。詳細については、以下の私の回答を参照してください。
Eric Fuller

5
これはナンセンスです。問題は、多くのアイテムの注文を送信することです。これは、多くの人が言っているように、1つのPOSTリクエストのエンティティで行うことができます。サーバーがそれをどのように処理するかは、まったく別のものです。この場合、注文の作成、その注文で可能なことの入力、および実行できなかった詳細の入力については問題ありません。これにより、ユーザーは注文を確認でき、N個を除くすべての商品が注文に追加されたが、一部は在庫切れであるか、システムがどう対処すべきかがわかりませんでした。もう一つの単純あまりユーザーフレンドリーなオプションはすべて拒否することである
thecoshman

2
@thecoshmanは3.25年で大きく変わります。おそらく、質問に対する完全に定式化された回答を投稿する必要があります。
dlamblin 14

3
@dlamblinええ、私はおそらく多くのことをするべきです...多分ある段階でそれを
達成する

9

Facebookはこれを行う方法を説明しています:https : //developers.facebook.com/docs/graph-api/making-multiple-requests

単純なバッチリクエスト

バッチAPIは、JSON配列として表される論理HTTPリクエストの配列を受け取ります。各リクエストには、メソッド(HTTPメソッドGET / PUT / POST / DELETEなどに対応)、relative_url(graph.facebookの後のURLの部分)があります。 com)、オプションのヘッダー配列(HTTPヘッダーに対応)およびオプションの本文(POSTおよびPUTリクエスト用)。Batch APIは、JSON配列として表される論理HTTP応答の配列を返します。各応答には、ステータスコード、オプションのヘッダー配列、およびオプションの本文(JSONエンコードされた文字列)があります。


1
これは非常に興味深いリンクであり、提案された解決策は私には使用できるようです。とにかく、StackOverflowでの好ましい回答は、リンクが変更または非表示になる可能性があるため、回答の本文にあるソリューションの概念を説明することです。
Jan Vlcinsky 2016年

7
これは実際にはFacebookのやり方であり、OPが尋ねたように必ずしもRESTfulであるとは限りません
0cd

バッチAPI(Google、Facebookなど-@PuneetAroraから)は、いくつかの無関係な要求を一緒にグループ化する場合により便利だと思います。1つのアイテムを作成するリクエストを作成し、それらすべてのリクエストをグループ化してアイテムのコレクションを送信することは「狂気」(Einstein)です。アイテムのコレクションを渡すリクエストを作成するだけです。
tfmontague 2017

8

あなたの考えは私には当てはまるようです。実装はあなたの好みの問題です。あなたはこれのためにJSONまたは単にパラメータ( "order_lines []"配列)を使用して行うことができます

POST /orders

1つのアクション(注文とその行)で一度により多くのリソースを作成するので、すべてのリソースを検証し、それらすべてが検証に合格した場合にのみ保存することが重要です。トランザクションで行う必要があります。



5

私は最近これに実際に取り組んでいますが、これが私が目指していることです。

複数のリソースを追加するPOSTが成功した場合、200 OKを返します(201を検討していましたが、ユーザーは最終的に、作成されたリソースにたどり着きませんでした)。 -のみまたは編集可能な方法。たとえば、ユーザーは、単一のファイル入力のみを含むフォームを使用して、複数の画像を選択し、ギャラリーにPOSTすることができます。POSTリクエストが完全に成功した場合、作成された画像リソース表現ごとにフォームのセットが表示され、それぞれについて詳細(名前、説明など)を指定できます。

1つ以上のリソースの作成に失敗した場合、POSTハンドラーはすべての処理を中止し、個々のエラーメッセージを配列に追加します。次に、419競合が返され、ユーザーは、送信されたフォームに戻る方法と同様に、エラー配列の内容を示す419競合エラーページにルーティングされます。


-2

100のオーダーラインのHTTPヘッダーを送信する必要はありません。また、必要以上のリクエストを生成する必要もありません。

注文全体を1つのJSONオブジェクトでサーバーに送信します:server / orderまたはserver / order / new。次のものを指すものを返します:server / order / order_id

POSTの代わりにCREATE PUTの使用も検討してください


私は彼がHTTP POSTメソッドを知っていると思います。CREATE HTTPメソッドのようなものはありません。
ミラノノボタ

ありませんか?ああ、そうではありませんでした。代わりにPUTがありました。
2009年

22
コンテンツの作成にPUTを使用する理由は何ですか?これがまさにHTTP POSTメソッドの目的です。
thecoshman 2013年

8
クライアントにwebdavのようにリソースのURIを指定させる場合は、PUTを使用してリソースを作成します。投稿者がPUTを使用することに同意しませんが、リソースを作成する場所がありますが、その場所の範囲は制限される場合があります。
user602525

2
注:エンティティをPOSTすると、エンティティはリクエストでアドレス指定されたリソースの下位になり、べき等ではありません。PUTはアドレスのエンティティを置き換え、べき等です。べき等(語?)は、消費者にとって重要な期待です。
ルークプレット16年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.