REST URIでアクション(動詞)を表す


16

お客様のドキュメントに対して実行する印刷操作があります。追加、更新、削除など、他の標準操作も実行する必要があります。だから、私は次のものを持っています:

  • 新しい顧客を作成する場合:
    URI = / customer / {id}、タイプ= POST、Methodname = CreateCustomer()
  • 更新の場合:
    URI:/ customer / {id}、タイプ= PUT、メソッド= UpdateCstomer()
  • 顧客の削除:
    URI = / customer / {id}、タイプ= DELETE、メソッド名= DeleteCustomer()
  • ビューの場合:
    URI:/ customer / {id}、タイプ= GET、メソッド= GetCustomer()

今、その顧客のためにドキュメントを印刷する必要がある場合、印刷機能が必要です。私のURIは次のようになります:/ customer / {id}、type = POST、method = PrintCustomer()。しかし、CreateCustomerにはそのURIとPOSTタイプを使用しました。URIを/ customer / Print / {id}、タイプ= POST、メソッド= PrintCustomer()のようにしたかったのです。

しかし、URIに「印刷」動詞を含めることはできません。これを行う最良の方法は何ですか?URIとして/ customer / document / {id}を考えましたが、同じ問題に遭遇します。「ドキュメント」に対してCRUD操作を実行します。それで、再び「印刷」に使用するものを使い果たしました。お知らせ下さい。


2
通常、印刷はクライアント側の操作なので、私は興味があります-コマンドをRESTサーバーに送信する必要があるようなセットアップはどうですか?
シャウナ

2
@Shauna必ずしもではありませんが、URIは、印刷しやすいバージョンのリソース(つまり、別のビュー)をサーバーに要求する場合があります。
エヴァンプライス

1
@EvanPlaice-まあまあですが、それでもクライアントに印刷するという行為は残っています(サーバー側の印刷に適したバージョンを取得した後でも、印刷するデバイスを決定し、印刷コマンド自体を送信します)コマンドはプリントサーバーに送信されます)。リソースの印刷対応バージョンを取得する要求は、論理的に...よく... GETになります。
シャウナ

@Shauna HTTP要求のみから印刷ジョブをトリガーすることは、ブラウザーのセキュリティのため不可能です。印刷に適したバージョンのリクエストは単なるGETリクエストですが、それでもブラウザーが印刷可能なバージョンをレンダリングするように指定する方法が必要です。別のURLを指定することもできますが、実際には別のリソースを要求するのではなく、同じリソースの別のトランスフォームだけを要求するため、RESTの原則に違反します。したがって、クエリパラメータやコンテンツタイプを介してトランスフォームを指定する理由。
エヴァンプライス

回答として投稿するのに十分な担当者がいませんが、tyk.io / rest-never-crudがそれPOST /customers/123/printが有効なことだと主張しているのは興味深いと思います。
jlh

回答:


9

POST「作成」を意味するのではなく、「プロセス」を意味します。適切なリクエストを既存のリソースに投稿する(つまり/customers、新しい顧客を作成するために投稿する)ことで、新しいリソースを作成できます。しかしPOST、きちんとしたCRUDパラダイムに対応しない他のすべてのアクションを埋めるために使用することもできます。

印刷の場合、印刷自体をリソースとして考える必要があります。システムに「印刷ジョブ」を作成するように依頼しています。これはprints/、要求されたすべての印刷のコンテナとして機能するリソースを持つことができることを意味します。あなたが何かをあなたPOSTが作成したい印刷物に関するすべての情報を含むこのリソースにドキュメントとして印刷したいとき、それらへのリンクで印刷したいリソースを特定します。

JSONドキュメントとしては、次のようになります。

{
   contents: ["http://site/customers/12345"],
   paper-size: "A4",
   duplex: "true"
}

明らかに、あなたがやりたいことに関連するようにこれをカスタマイズする必要があります。重要なことは、URLを指定することにより、印刷する他のリソースを識別することです。

リクエストへの応答として、単純にa 200 OKまたはa 204 No-Contentを返して、それを火と忘れのプロセスとして扱うことができます。ただし、拡張する場合201 Createdは、新しく作成した印刷ジョブのURLを返し、指定できます(例:)/prints/12345

その後、ユーザーはGETリソースでを実行して印刷ジョブのステータス(保留、進行中など)を確認したり、を発行してジョブのキャンセルを要求したりできDELETEます。

リソースの観点から問題を言い換えると、RESTfulなデザインは自然に生まれ、すぐには考えられなかった方法で拡張および強化する機会を与えるはずです。


2
POSTは通常、作成/挿入を意味し、putは通常、更新の保存/更新を意味します。これは、HTMLで通常使用される方法ではない場合でも、RESTで定義される方法です。
エヴァンプライス

2
@EvanPlaiceは、HTTP仕様のPUTをcreate / update動詞(より使い慣れたcreate + retrieve + updateの代わりにcreate + updateモデルを使用)として指定し、POSTは「data processing」動詞および「append」動詞です。 。彼のブログのRoy Fieldingは、操作を標準化したくないときに使用する動詞としてPOSTを説明しました。POSTは、アイテムのコレクションに新しいアイテムを追加することを考慮すると、「作成」セマンティクスを使用します。この場合、Tragedianは、印刷ジョブの処理または追加のためにPOSTを使用して頭に釘を打ちました。
ロブ14

@RobY OK、それは理にかなっています。例として、PUTを使用して、データベースにデータを入力するように設計されたSPROCを表すことができます。一方、POSTは、そのデータの収集/準備に必要な中間ステップと突然変異を構成できます。POST操作のデザインは、デザインの進化に応じて変更または置き換えられる可能性がありますが、PUT操作は(理想的には)変更しないモデルを表します。私は答えを更新しますが、これはすでに違いを説明する素晴らしい仕事をしています。
エヴァンプライス

4

前にこれをやった。ドキュメントを印刷するには、pdfバージョンのリソースを返すだけです。クライアントは、Acceptヘッダーapplication / pdfを持つリソースのGETリクエストを送信するだけです。

これにより、印刷ジョブなどの一時リソースの新しいURIの作成も回避されます。HTTPヘッダーの使用もRESTの一部であり、URIをクリーンに保ちます。


3

現在のURIのGETにパラメーターを追加するだけです

複数のアクションにURIを使用するのは非常に一般的です。

同じリソースで異なるアクションについて説明している場合は、それをパラメーターとして定義します。

/ customer / {id}?print = true

次に、GETメソッドを定義する場所で、印刷パラメーターの存在を検出し、異なる方法で処理します。

RESTは次の方法で定義されます。

  • POST-レコード、アセット、またはリソースを作成します
  • PUT-更新、レコード、資産、またはリソース
  • DELETE-レコード、アセット、またはリソースを削除します

一方、GETは複数の方法で使用することを意図しています。これは、通常、リソースを取得できるさまざまなフォームが多数あるためです。GETリクエストがクエリ文字列として表されるのもそのためです。データベースリソースを使用していた場合、文字通りクエリを介してビューを取得することになりますが、RESTはさまざまなタイプのリソースを処理するように設計されているため、意図的に高レベルに抽象化されます。

RESTの仕様は、APIがごく最近使用し始めたばかりですが、かなり前向きです。

RESTプロトコルについて詳しく知りたい場合は、「Haters Gonna Honna HATEOAS」を読むことを強くお勧めします。


更新:

@Shaunaは私の推論に興味深い穴を指摘しました。真の正しい方法はなく、多くの形式が受け入れられると考えられています。もう少し考えましたが、データを別の表現に変換するのが目的なので、変換を新しいMIMEタイプとして定義するのが理にかなっています。

たとえば、URIを次のように表すことができます。

/customer/{id}+print

応答のContent-Typeをtext / html + printに設定できる場所。そうすれば、将来、より多くの変換を定義するオプションもあります。

例えば:

// for application/json
/customer/{id}+json

// for application/atom+xml
/customer/{id}+atom

どちらの方法でも、すべてのフォームが受け入れられます。決定する実装は、個人の好みとサーバーの機能にさらに依存します。

余談:混乱があるようですので、明確にさせてください。リソースの変換方法を指定するには、「print」クエリパラメータまたはコンテンツタイプ、あるいはその両方を使用します。物理的な印刷ジョブをトリガーする方法ではありません。セキュリティ上の理由から、ハードウェアレベルのアクセスは常にユーザー/クライアント/ブラウザーに任されています。


追加するには-クエリ文字列(?print=true)を使用する代わりに、URIパラメータ(つまり- /customer/{id}/printable)を使用することもできます。どちらを使用するかは、システム(CMS、フレームワーク、一般的なコード)が処理するように設定されている標準に大きく依存します。両方とも有効かつ許容されると見なされます
シャウナ

@Shauna技術的には、URI '/ customer / {id} + print'での印刷に固有のMIMEタイプと、text / html + printの応答MIMEタイプを使用することが最善のアプローチです。このようなアプローチの利点は、同じURIに対して多くのMIMEタイプ(text / html、text / x-markdown、application / jsonなど)の変換を作成できることです。提示するソリューションの欠点は、MIMEタイプごとに追加のURIを作成する(および別のルートを定義する)必要があることです。これは、RESTを使用する目的をやや損ねます。
エヴァンプライス

(続き)URIハックは主にRORコミュニティによって導入されたアンチパターンであると主張しますが、それはそれらが役に立たないという意味ではありません。より良い低レベルのHTTPdサーバーの登場により、RESTの可能性を最大限に活用する方法でRESTを実装することが容易になりつつあります。Apacheとindex.htmlを介してすべてをルーティングすることが唯一の選択肢であった時代から、物事は大きな進歩を遂げました。
エヴァンプライス

2
GETは状態を変更したり、副作用を引き起こしたりしないでください。GETはi等であると考えてください。つまり、ミドルウェアは、要求が通過しなかった場合に要求を再試行する可能性があることを意味します。この場合、再試行のたびに、新しく新しく印刷されたドキュメントのコピーが作成されます。;)
ロブ14

@RobY「印刷」アクションは、ドキュメントを物理的に印刷するプロセスを処理しないと想定していました。これは、ブラウザーとプリントドライバーの方が適切に処理されるためです。むしろ、メディア/印刷出力はドキュメントの「印刷に適した」表現を返します。したがって、べき等性が維持されます。良い点は、インターネットを介してステートレスな方法で印刷ジョブを送信するのは悪い時間でしょう。
エヴァンプライス
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.