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
後者のスキームでは、リソースのURLに動詞を保持します。 HTTP動詞はその目的で使用する必要があるため、これは避けてください。それを無視したり、複製したり、上書きしたりする代わりに、基礎となるプロトコルを採用してください。
DELETE /item/delete/:id
、同じリクエストに同じ情報を2回入れます。これは不必要であり、回避する必要があります。個人的に、私はこれと混同されます。 APIは実際にDELETE
リクエストをサポートしていますか? URLにdelete
を配置し、代わりに別のHTTP動詞を使用するとどうなりますか?何か一致しますか?もしそうなら、どれが選ばれますか?適切に設計されたAPIのクライアントとして、私はそのような質問をする必要はありません。
DELETE
またはPUT
リクエストを発行できないクライアントを何らかの形でサポートするために必要な場合があります。その場合は、この情報を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仕様に反しない限り、これらの動詞(またはそのサブセット)をアプリケーションセマンティクスの任意のセットにマップできます。たとえば、許可されるすべての操作が safeとidempotent 。上記のマッピングは、ユースケースに適合し、仕様に準拠している例にすぎません。必ずしもこのようにする必要はありません。
また、真にRESTfulなAPIでは、HATEOAS(アプリケーション状態のエンジンとしてのハイパーテキスト)の原則 に準拠している限り、プログラマーが利用可能なURLの詳細なドキュメントを読む必要はありません。 REST の中核となる仮定。リンクは、クライアントアプリケーションがリンクを理解して使用し、アプリケーションの状態遷移の可能性を理解できる限り、人間にはまったく理解できません。
最初の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
_と言った場合、「ID 123のユーザー削除者レコードを削除する」ことを意味しているようですが、これはおそらく言いたいことではありません。そして、この状況でより適切な動詞を使用した場合でも、「POST/user/delete/123」と表示され、「ID 123のユーザー削除者にアタッチされた操作を実行してください」と表示されますが、レコードを削除するという遠回りの方法です(これは英語の動詞の名詞化に似ています)。
URLについて考えることができる1つの方法は、URLをオブジェクト指向のプログラミングにおけるオブジェクトとしてのオブジェクトおよびリソースへのポインターのように扱うことです。 _GET /user/123
_、_DELETE /user/123
_を実行すると、それらをオブジェクト内のメソッドと考えることができます。[/user/123].get()
、[/user/123].delete()
ここで、_[]
_はポインター逆参照演算子。ただし、URLの場合(ポインターを持つ言語がわかっている場合)。 RESTの基本的な原則の1つは、統一されたインターフェースです。つまり、リソース/オブジェクトの広大なネットワークのすべてで機能する動詞/メソッドの小さな限定されたセットを持っています。
したがって、最初の方が優れています。
PS:もちろん、これはRESTを最も純粋な方法で見ています。時々実用性が純粋さを上回り、適切なRESTを実行することを困難にする脳死したクライアントまたはフレームワークの譲歩をする必要があります。
(申し訳ありませんが、初めて(2)の/ edit /と/ delete /を逃しました...)
URIの考え方は、それがメソッド呼び出しではなくアドレス可能なリソースの識別子であるということです。したがって、URIは特定のリソースを指す必要があります。また、URIを参照する場合は、常に同じリソースを取得する必要があります。
つまり、データベースの行の主キーと同じ方法でURIを考える必要があります。それは何かを一意に識別します:Universal Resource Identifier。
したがって、複数形を使用する場合も単数形を使用する場合も、URIはinvocationではなくidentifierにする必要があります。あなたがやろうとしていることdoはメソッドに含まれます:GET(get)、PUT(create/update)、DELETE(delete)またはPOST(everythingそうしないと)。
したがって、「/ item/delete/123」はRESTを中断します。これは、リソースを指さないため、メソッドの呼び出しに近いということです。
(また、意味論的には、URIを取得し、それが古いことを確認してから削除できますsame URI-識別子であるためです。GETURIに "/ delete/"とDELETEを実行すると、HTTPセマンティクスに反します。リソースごとに2つ以上のURIをブロードキャストし、1を実行します。)
今、チートはこれです:リソースであるものとそうでないものの明確な定義はないため、RESTの一般的な回避は、「処理名詞」を定義し、URIにそれはほとんどWordのゲームですが、セマンティクスを満たしています。
たとえば、何らかの理由で実際にこれを使用できなかった場合は、次のようになります。
DELETE /items/123
「削除者」処理リソースがあることを世界に宣言して使用することができます
POST /items/deletor { id: 123 }
これはRPC(リモートプロシージャコール)によく似ていますが、HTTP仕様で指定されているPOST仕様の "データ処理"句の膨大な抜け穴を通り抜けます。
ただし、これは一種の例外であり、もしcanを使用すると、作成/更新に共通のPUTを使用し、削除にDELETEを使用し、追加、作成、および削除にPOSTそれ以外はすべてすべきです。これは、HTTPのより標準的な使用法であるためです。ただし、「コミット」、「公開」、または「編集」などのトリッキーなケースがある場合は、プロセッサを使用するケース名詞はREST純粋主義者を満たし、必要なセマンティクスを提供します。