RESTful API:共有または特定のURLを持つHTTP動詞?


25

RESTful APIの作成中、同じURLでHTTP動詞を使用する必要がありますか(可能な場合)、またはアクションごとに特定のURLを作成する必要がありますか?

例えば:

GET     /items      # Read all items
GET     /items/:id  # Read one item
POST    /items      # Create a new item
PUT     /items/:id  # Update one item
DELETE  /items/:id  # Delete one item

または、次のような特定のURLを使用します。

GET     /items            # Read all items
GET     /item/:id         # Read one item
POST    /items/new        # Create a new item
PUT     /item/edit/:id    # Update one item
DELETE  /item/delete/:id  # Delete one item

回答:


46

後者のスキームでは、リソースのURLに動詞を保持します。HTTP動詞はその目的に使用する必要があるため、これは避ける必要があります。基になるプロトコルを無視、複製、またはオーバーライドするのではなく、採用します。

DELETE /item/delete/:idご覧ください。同じリクエストに同じ情報を2回配置します。これは不要であり、回避する必要があります。個人的に、私はこれと混同されるでしょう。APIは実際にDELETEリクエストをサポートしていますか?deleteURL に配置し、代わりに別のHTTP動詞を使用するとどうなりますか?何かにマッチしますか?その場合、どれが選択されますか?適切に設計されたAPIのクライアントとして、このような質問をする必要はありません。

たぶん、発行DELETEPUTリクエストができないクライアントをサポートするために必要になるでしょう。その場合は、この情報をHTTPヘッダーで渡します。一部のAPIは、X-HTTP-Method-Overrideこの特定の目的のためにヘッダーを使用します(とにかく非常に見苦しいと思います)。私は確かにパスに動詞を入れません。

をやる

GET     /items      # Read all items
GET     /items/:id  # Read one item
POST    /items      # Create a new item
PUT     /items/:id  # Update one item
DELETE  /items/:id  # Delete one item

動詞について重要なことは、それらがHTTP仕様で既に十分に定義されており、これらのルールに沿っていることで、アプリケーションセマンティクスではなくHTTPのセマンティクスを理解するアプリケーション外部のキャッシュ、プロキシ、およびその他のツールを使用できることです。URLに含めることを避けるべき理由は、読み取り可能なURLを必要とするRESTful APIに関するものではないことに注意してください。不要なあいまいさを回避することです。

さらに、RESTful APIは、HTTP仕様に反しない限り、これらの動詞(またはそのサブセット)をアプリケーションセマンティクスのセットにマッピングできます。例えば、できることすべての操作がある場合にのみ、使用法が要求をGETすることをRESTfulなAPI構築することは完全に可能である両方の安全冪等を。上記のマッピングは、ユースケースに適合し、仕様に準拠している単なる例です。必ずしもこのようにする必要はありません。

真のRESTful APIは、RESTの中核となる前提の1つである HATEOAS(アプリケーション状態のエンジンとしてのハイパーテキスト)の原則に準拠している限り、プログラマーが利用可能なURLの詳細なドキュメントを読む必要はありません。クライアントアプリケーションがリンクを理解して使用し、可能なアプリケーション状態の遷移を把握できる限り、リンクは人間にはまったく理解できません。


4
PUTおよびがない場合DELETE、クエリ文字列で区別せずに、パスに追加することをお勧めします。既存の操作に対するクエリ文字列の変更ではありません。それは別の操作です。
ロバートハーヴェイ14年

4
この場合の@RobertHarveyは、とにかくハックと呼びます。あなたが言うように、それは操作であり、それはRESTfulを目指すAPIを設計するときに私がパスに入れたものではありません。クエリ文字列に配置するだけで、侵襲性が低くなります。それはキャッシュを防ぎますが、この種のリクエストへの応答はとにかくキャッシュされるべきではないと思います。また、APIのコンシューマーは、URLを解析または構築せずにメソッドを簡単に示すことができます。理想的には、クライアントが自分でURLを作成する必要なく、真のRESTful APIがハイパーリンクを提供する必要があります。
トニエズヴィエズ14年

すべての動詞がなければ、とにかく完全にRESTfulではありませんか?
ロバートハーヴェイ14年

@RobertHarvey trueですが、私はこれらを意図した設計ではなくフォールバックとして扱います。APIは実際のHTTPメソッドをサポートし、何らかの理由でそれらを実装できないクライアントがある場合、それらの使用法をこれらのクエリパラメーターに置き換えることができると思います。プロキシは、これらをオンザフライで取得し、サーバーが気にする必要さえないように、本物のHTTP動詞を使用して要求に変換することさえできます。真のRESTfulなAPIはほとんどありません。汎用Web APIに関しては、本当に好みの問題です。個人的には、きれいなURLを探します。私見を理解しやすい。
トニエズウィエズ14年

1
説明したように、@ RobertHarveyは、それらを使用するための意図された方法ではありません。これは、クライアントの制限を克服しなければならない場合の、2つの悪の少ない方だと思います。私はそのようなAPIのドキュメントを読んだことを思い出しますが、それを見つけるにはブラウザの履歴/ブックマークで発掘を行う必要があります。考えてみると、この場合はヘッダーの方が良いかもしれません。同意しますか?
トニエズヴィエズ14年

14

最初の1つ。

URI / URLはリソース識別子です(名前のヒント:ユニフォームリソース識別子)。最初の規則では、「GET / user / 123」を行うときに話されるリソースと「DELETE / user / 123」を行うときに話されるリソースは、同じURLを持っているため、明らかに同じリソースです。

2番目の規則では、「GET / user / 123」と「DELETE / user / delete / 123」が実際に同じリソースであることを確認することはできません。また、リソースではなく関連するリソースを削除していることを意味するようですそれ自体、削除することが/user/delete/123実際に削除することはむしろ驚くべきこと/user/123です。すべての操作が異なるURLで機能する場合、URIはリソース識別子として機能しなくなります。

と言うときはDELETE /user/123、「 'id 123のユーザーレコードを削除」と言っています。あなたが言う場合、あなたDELETE /user/delete/123が示唆していると思われるのは、「「123」のユーザー削除者レコードを削除する」ことです。これはおそらくあなたが言いたいことではないでしょう。そして、この状況でより正しい動詞「POST / user / delete / 123」を使用する場合でも、「 'id 123のユーザー削除者にアタッチされた操作を実行してください」と言っても、レコードを削除すると言う迂遠な方法です(これは英語の動詞の名詞化に似ています)。

URLについて考えることができる1つの方法は、オブジェクト指向プログラミングでオブジェクトやリソースへのポインタのように扱うことです。あなたが行うとGET /user/123DELETE /user/123:、あなたは、オブジェクトのメソッドと考えると考えることができ[/user/123].get()[/user/123].delete()どこ[](あなたはポインタを持っている言語を知っている場合)演算子を逆参照ポインタのようなもののURLのです。RESTの基本原則の1つは、統一されたインターフェイスです。つまり、リソース/オブジェクトの広大なネットワーク内のすべてに対して機能する動詞/メソッドの小規模で限定されたセットを持つことです。

したがって、最初の方が優れています。

PS:もちろん、これはRESTを最も純粋な方法で見ています。実用性が純粋さを上回る場合があり、適切にRESTを実行するのを困難にする脳死クライアントまたはフレームワークに譲歩する必要があります。


OOPの例では+1 :)
53777A 14年

6

(申し訳ありませんが、最初の(2)で/ edit /と/ delete /を見逃しました...)

URIの考えはそれがメソッド呼び出しよりむしろアドレス可能なリソースの識別子であるということです。したがって、URIは特定のリソースを指す必要があります。また、URIを尊重する場合は、常に同じリソースを取得する必要があります。

つまり、データベースの行の主キーについて考えるのと同じ方法で、URIについて考える必要があります。何かを一意に識別します:Universal Resource Identifier。

したがって、複数形を使用する場合も単数形を使用する場合も、URIは呼び出しではなく識別子である必要があります。あなたがしようとしていることは、メソッド、すなわち:GET(取得)、PUT(作成/更新)、DELETE(削除)またはPOST(他のすべて)に行きます。

そのため、「/ item / delete / 123」はRESTを中断します。これは、リソースを指していないため、メソッド呼び出しに近いためです。

(また、意味的に、URIを取得し、それが古くなっていると判断し、同じ URIを削除できるようにする必要があります。これは識別子であるためです。GETURIに「/ delete /」がなく、DELETE HTTPセマンティクスに反します。リソースごとに2つ以上のURIをブロードキャストします。

さて、これはごまかしです。リソースとリソースの明確な定義はありません。そのため、RESTの一般的な回避策は、「処理名詞」を定義してURIを指すことです。これはほとんど単語ゲームですが、セマンティクスを満たします。

したがって、たとえば、何らかの理由でこれを実際に使用できなかった場合:

DELETE /items/123

「削除者」処理リソースがあることを世界に宣言して使用することができます

POST /items/deletor  { id: 123 }

これは、RPC(リモートプロシージャコール)によく似ていますが、HTTP仕様で指定されているPOST仕様の「データ処理」句の広大な抜け穴に陥ります。

あなたはしかし、それを行うことは一種の例外的であり、かつでき、作成/更新するための共通のPUTを使用して、削除のためのDELETE、およびPOST APPENDのために、作成、および他のすべては、あなたがすべきことは、HTTPのより標準的な使用だから、。しかし、「commit」、「publish」、または「redact」のようなトリッキーなケースがある場合、プロセッサーの名詞を使用するケースはRESTの純粋主義者を満たし、必要なセマンティクスを提供します。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.