RESTfulな方法でリソースのサーバー側メソッドを呼び出す
私はRESTについて初歩的な理解を持っていることに留意してください。例えば、以下のようなURLがあるとします。
http://api.animals.com/v1/dogs/1/
そして今、私はサーバーに犬を吠えさせたいのです。この方法はサーバーだけが知っています。例えば、10分ごとに犬を吠えさせるCRONジョブを永遠に実行させたいとします。その呼び出しはどのようなものでしょうか?私はこれをやってみたいんです。
URLを要求します。
ACTION http://api.animals.com/v1/dogs/1/
リクエストボディに
{"action":"bark"}
自分でHTTPメソッドを作ったことを怒られる前に、RESTfulな方法でサーバーサイドのメソッドを呼び出す方法について、もっと良いアイデアを教えてください:)
明確化のための編集
bark"メソッドが何をするのかについて、もう少し明確にしました。異なる構造のAPIコールになる可能性があるオプションをいくつか紹介します。
- bark は dog.email にメールを送信するだけで、何も記録しません。
- dog.email にメールを送信し、dog.barkCount を 1 だけ増加させる。
- barkは新しい"bark"レコードを作成し、bark.timestampに吠えた時の記録を残します。また、dog.barkCountを1つ増やします。
- Githubから最新バージョンのdogのコードを取得するためにシステムコマンドを実行します。そして dog.owner にテキストメッセージを送信し、新しい dog コードが本番環境にあることを伝えます。
135
3
なぜRESTfulな設計を目指すのか?
RESTfulの原則は、Webサイトを簡単にする機能(ランダムな人間のユーザーが"surf"するために)をWebサービスのAPIデザインに持ち込むことで、プログラマにとって使いやすいものにします。[RESTはRESTだから良いのではなく、RESTだから良いのです][1] そして、それが良いのは、ほとんどがシンプルだからです。 SOAPエンベロープや単一URIのオーバーロードされた
POST
サービスがない)プレーンなHTTPのシンプルさは、人によっては "lack of features" と呼ぶかもしれませんが、実は その最大の強み なのです。この2つの基本的な設計上の決定が、今日のメガサイト(とメガサービス)にまでHTTPのスケーラビリティを維持しているのです。 しかし、RESTは銀の雄たけびを上げるものではありません。時にはRPCスタイル(SOAPなどのRemote Procedure Call")が適切な場合もあり、他のニーズがWebの良さよりも優先される場合もあります。これはいいことです。私たちが本当に嫌なのは、不必要な複雑さです。プログラマーや企業が、古いHTTPで十分に処理できる仕事を、RPCスタイルのサービスで行うことがあまりに多いのです。その結果、HTTPは、何が起こっているのかを説明する巨大なXMLペイロードのためのトランスポートプロトコルに成り下がってしまいます(URIやHTTPメソッドは、それについての手がかりを与えません)。その結果、サービスはあまりにも複雑で、デバッグが不可能になり、クライアントが開発者の意図通りの 正確な設定 をしていない限り、動作しません。 Java/C#のコードがオブジェクト指向でないのと同じように、HTTPを使用するだけではRESTfulなデザインにはなりません。アクションとリモートメソッドという観点から、自分のサービスを考えることに夢中になるかもしれません。これでは、RPCスタイルのサービス(またはREST-RPC-ハイブリッド)になってしまうのも無理はない。最初のステップは、異なる考え方をすることです。RESTfulな設計は多くの方法で達成することができます。1つの方法(最も単純な方法と言う人もいます)は、**アクションではなくリソースの観点からアプリケーションを考えることです。最初のデザインについて
それでは、デザイン案を見てみましょう。
まず最初に、新しいHTTP動詞 (
ACTION
) を作成することを検討すべきではありません。一般的に言って、これはいくつかの理由から 望ましくありません 。ACTION
動詞が存在することを知ることができるでしょうか?POST
** を使うことを検討してみましょう (理由は後述します。今は私の言葉を信じてください)。これはOKかもしれませんが、以下の場合のみです。
URI は "dog" リソース (おそらく
id==1の犬) を表し、ドキュメントプロセッサを表すものではありません。 つまり、今わかっているのは、上記のデザインはあまりRESTfulではないということですが、それは具体的にどのようなことなのでしょうか?**基本的に、それは複雑な意味を持つ複雑なURIであるため、悪いことなのです。そこから何かを推論することはできません。プログラマはどうやって犬が
barkというアクションを持っていて、それに
POST` を密かに注入できることを知ることができるでしょうか?質問のデザイン'APIコール
そこで、本題に入り、リソースの観点から考えて、RESTfulに吠え声をデザインしてみましょう。Restful Web Services][3]の本を引用させてください。 POST
リクエストは、既存のリソースから新しいリソースを作成する試みである。 gt;一つです。既存のリソースは、新しいリソースの親になる可能性があります。 データ構造的な意味で、ツリーのルートがすべての その葉ノード。あるいは、既存のリソースは、特別な *"factory"* である可能性があります。 他の資源を生み出すことだけを目的とした資源。このリソースは POST
リクエストと一緒に送信される表現には、初期の 新しいリソースの状態です。PUT と同様に、POST
リクエストは、以下のことを行う必要はありません。 表現が含まれます。 上記の説明から、bark` はdog
のサブリソースとしてモデル化できることがわかります(bark
は dog の中に含まれているので、つまり、bark は "barked" by** a dog であるため)。 この推論から、我々はすでにPOST
です。/barks
で、dog のサブリソースである。v1/dogs/1/barksで、これは
barkの "factory" を表します。このURIはそれぞれの犬に対して一意です(
/v1/dogs/{id}`の下にあるため)。 さて、あなたのリストのそれぞれのケースは、特定の動作を持っています。1. bark は
dog.email
にメールを送るだけで、何も記録しません。まず、吠える(メールを送る)のは同期タスクなのか非同期タスクなのでしょうか?次に、
bark
のリクエストは何かドキュメント(メールかもしれません)を必要としますか?それとも空ですか?1.1 barkは
dog.email
にメールを送信し、何も記録しません(同期タスクとして)このケースは単純です。ファクトリーリソース
何も記録(変更)しないので、`200 OK`で十分です。これは、すべてが期待通りに行ったことを示します。barks
を呼び出すと、すぐに吠え声(メールの送信)が聞こえ、その応答(OKかどうか)がすぐに与えられます。### 1.2 樹皮が `dog.email` にメールを送り、何も記録しない (非同期タスクとして) この場合、クライアントは `bark` タスクを追跡する方法を持たなければなりません。その場合、`bark`タスクはそれ自身のURIを持つリソースである必要があります。 この方法では、それぞれの`bark`を追跡することができます。クライアントは `bark` の URI に対して `GET` を発行して、現在の状態を知ることができます。もしかしたら、`DELETE`でキャンセルすることもできるかもしれません。
## 2. バークは `dog.email` にメールを送り、`dog.barkCount` を 1 だけ増やします。 もし、`dog` リソースが変更されたことをクライアントに知らせたい場合、これはより厄介なことになります。 この場合、`location`ヘッダ'の意図は、クライアントに`dog`を見るべきだということを知らせることです。HTTP RFC about `303`][4] からです。 > このメソッドは主に POST`で起動されたスクリプト**は、ユーザーエージェントを選択したリソースにリダイレクトします。 タスクが非同期の場合、 `1.2` の場合と同様に `bark` サブリソースが必要で、タスクが完了したら `GET .../barks/Y` で `303` が返される必要があります。
## 3. bark は新しい "`bark`" レコードを作成し、`bark.timestamp` が吠えた時の記録を作成します。また、`dog.barkCount`を1つ増加させます。 ここでは、リクエストによって `bark` が作成されたので、ステータス `201 Created` が適用されています。 非同期で作成された場合は、代わりに `202 Accepted` が必要です([HTTP RFC に記載されています][5])。 保存されたタイムスタンプは `bark` リソースの一部であり、 `GET` で取得することができます。更新された犬は `GET dogs/X/barks/Y` の中で "documented" することができます。
## 4. bark は Github から最新版の dog のコードを取得するためにシステムコマンドを実行します。そして `dog.owner` に新しい dog のコードが本番環境にあることを伝えるテキストメッセージを送ります。 この文言は複雑ですが、ほとんど単純な非同期タスクです。 クライアントは `/v1/dogs/1/barks/a65h44` に `GET`s を発行して、現在の状態(コードが引き出された場合、オーナーにメールが送られた場合など)を知ることができるようになります。犬が変わるたびに、`303`が適用されます。
## ラッピング 引用元: [ロイ・フィールディング][6]。 RESTがメソッドに要求する唯一のことは、メソッドが統一されていることです。 すべてのリソースに対して定義されている(つまり、仲介者が の意味を理解するために、リソースの種類を知る必要があります。 リクエスト)。 上記の例では、 `POST` は一律に設計されています。これは、犬を "`bark`" させます。これは安全ではありませんし(吠えることはリソースに影響を与えるという意味)、べき等でもありません(それぞれのリクエストが新しい `bark` を生成します)。これは `POST` という動詞によく当てはまります。 プログラマーなら、 `barks` への `POST` は `bark` を生成する、ということが分かるでしょう。レスポンスのステータスコード(必要であればエンティティボディやヘッダも)は、何が変わったのか、クライアントはどうすればいいのかを説明する役割を担っています。 Note: 使用した主なソースは、"[Restful Web Services][3]" book, [HTTP RFC][7] and [Roy Fielding's blog][8].
ほとんどの人は、この目的のためにPOSTを使用します。 これは、他のHTTPメソッドが適切でないと思われる場合に、安全でない操作や非べき等な操作を行うのに適しています。
XMLRPC][1] のような API は、任意のコードを実行できるアクションを起動するために POST を使用します。 POSTデータにはquot;action"が含まれます。
RESTはリソース指向の規格であり、RPCのようなアクションドリブンではない。
もし、サーバーにbarkさせたいなら、JSON-RPCのような別のアイデアや、websocket通信に目を向けるべきでしょう。
私の意見では、RESTful に保とうとすると失敗します。
action
パラメータでPOST
を発行すれば、新しいリソースを作成するわけではありませんが、副作用があるかもしれないので、より安全だと思います。