rest チュートリアル
休憩を開始する
サーチ…
備考
このセクションでは、残りのものの概要と、開発者がそれを使用する理由について概説します。
また、休憩中の大きな科目についても言及し、関連するトピックにリンクする必要があります。休憩のためのドキュメンテーションは新しいものなので、それらの関連トピックの初期バージョンを作成する必要があります。
RESTの概要
RESTは、プレゼンテーションSのテートのT ransferをREの略で、彼の博士論文でロイ・フィールディングで鋳造された建築スタイルとネットワークベースのソフトウェアアーキテクチャの設計 。その中で、彼は以下のような特定のアーキテクチャ上の原則を特定します。
アドレス可能なリソース:RESTにおける情報とデータのキー抽象化はリソースであり、各リソースはURIを介してアドレス可能でなければならない。
統一された制約のあるインターフェース:リソースを操作するための小さな定義済みメソッドの使用。
表現指向:あるURIによって参照されるリソースは異なるフォーマットを持つことができ、異なるプラットフォームには異なるフォーマットが必要です。たとえば、ブラウザにはHTMLが必要で、JavaScriptにはJSONが必要で、JavaアプリケーションにはXML、JSON、CSV、テキストなどが必要です。そのサービスの表現を使用します。
ステートレスに通信:ステートレスアプリケーションは拡張しやすくなります。
アプリケーション状態のエンジンとしてのハイパーメディア:私たちのデータフォーマットは、アプリケーションの状態遷移を促します。
これらのアーキテクチャ原則のセットはRESTと呼ばれます。 RESTの概念はHTTPの概念に触発されています。 RESTに与えたRoy Fieldingは、HTTP仕様の作成者の一人です。
WebサービスとRESTful Webサービスは、プログラムによるアクセスのためにインターネットに公開されているサービスです。彼らは私たちのコードから呼び出すことができるオンラインAPIです。 「ビッグ」Webサービス SOAPとREST Webサービスの2種類があります。
RESTfulなWebサービス :RESTアーキテクチャの概念を適用して作成されたWebサービスは、RESTful Web Servicesと呼ばれ、システム・リソースと、HTTPプロトコルを介して異なるクライアントにリソースの状態を転送する方法を中心に説明します。
このドキュメントはRESTfulなWebサービスのみに焦点を当てていますので、SOAP WSの詳細については触れません。
RESTfulなWebサービスを設計する際に厳しい規則はありません。
- プロトコル標準なし
- 通信チャネルの標準がありません
- サービス定義標準なし
しかし、SOAPにはこれらのすべてに対して厳しい規則があります。すべてのSOAP Webサービスは、すべてのSOAP Webサービスの内容を規定するSOAP仕様に従います。この仕様は、委員会によって開発され、管理されています。SOAP WSが単一のルールにも従わない場合、定義上、SOAPはSOAPではありません。
RESTful Webサービスの概念
RESTful APIを設計/開発する際に考慮する必要があるガイドラインはほとんどありません。
- リソースベースの場所/ URI
- HTTPメソッドの適切な使用
- HATEOAS(アプリケーション状態のエンジンとしてのハイパーメディア)
RESTful APIを開発する際の主なアプローチは、APIを「可能な限りRESTful」にすることです。
REST over HTTP
RESTは、分散システムのクライアントをサーバーから切り離すために、クライアントとしてのWebブラウザーの実績のある概念を一般化した論文の中でRoy Fieldingが提案したプロトコルに依存しないアーキテクチャーです (第5章はRESTのプレゼンテーションです)。
サービスやAPIをRESTfulにするためには、次のような制約に従わなければなりません:
- クライアントサーバー
- ステートレス
- キャッシュ可能な
- 階層化システム
- 統一インタフェース
- リソースの識別
- リソース表現
- 自己記述的なメッセージ
- ハイパーメディア
Fieldingの論文で言及されている制約の他に、彼のブログ記事では、 REST APIはハイパーテキスト駆動でなければならず 、Fielding はHTTP経由でサービスを呼び出すだけではRESTfulにならないことを明らかにしました。したがって、サービスは、以下のように要約されるさらなるルールを尊重すべきである:
APIは、基礎となるプロトコルに準拠していて、違反していない必要があります。ほとんどの場合、RESTはHTTP経由で使用されますが、このプロトコルに限定されません。
リソースに重点を置き、メディア型を介したプレゼンテーション。
クライアントは、利用可能なリソースやその返された状態( 「タイプされた」リソース )について、APIの初期の知識や前提条件を持ってはいけません。これにより、クライアント実装を破ることなく、簡単にリソースを移動したり名前を変更したりすることができます。
リチャードソン成熟モデル
リチャードソン成熟度モデルは、RESTful Webサービスを取得するために、HTTPを介してREST制約を適用する方法です。
Leonard Richardsonはアプリケーションを次の4つのレイヤーに分けました。
- レベル0:トランスポートにHTTPを使用する
- レベル1:リソースを識別するためのURLの使用
- レベル2:インタラクションのHTTP動詞とステータスの使用
- レベル3: HATEOASの使用
リソースの状態の表現に重点を置くので、同じリソースに対する複数の表現をサポートすることが推奨されます。したがって、表現はリソース状態の概要を提示することができ、他方は他のものが同じリソースの完全な詳細を返すことができる。
Fielding制約が与えられた場合、 APIはRMMの第3レベルが実装された時点でのみ効果的にRESTfulになります 。
HTTPリクエストとレスポンス
HTTPリクエストは次のとおりです。
HTTP応答は次のとおりです。
- ほとんどの場合、 2xx(成功) 、 4xx(クライアントエラー)または5xx(サーバーエラー)のいずれかのステータス。
- ヘッダー(Key-Valueペア)
- ボディ(別名ペイロード、データ)
HTTP動詞の特性:
- 本文を持つ動詞:
POST
、PUT
、PATCH
- 安全でなければならない動詞(すなわち、リソースを変更してはならない動詞):
GET
- 冪等でなければならない動詞(つまり、複数回実行するとリソースに再び影響を与えてはならない):
GET
(無能力)、PUT
、DELETE
body safe idempotent
GET ✗ ✔ ✔
POST ✔ ✗ ✗
PUT ✔ ✗ ✔
DELETE ✗ ✗ ✔
PATCH ✔ ✗ ✗
したがって 、HTTP動詞をCRUD関数と比較することができます。
PUT
リクエストは、クライアントに更新された値でリソース全体を送信するように要求することに注意してください。リソースを部分的に更新するには、 PATCH
動詞を使用できます( リソースの部分的な更新方法を参照)。
通常のHTTP応答ステータス
成功
- 201(作成済み) :リソースが作成されました
- 202(受諾済み) :要求は受け入れられましたが、処理はまだ進行中です。
- 204(コンテンツ無) :要求は満たされ、追加のコンテンツはありません
- それ以外の場合: 200(OK)
リダイレクション
- 304(NOT MODIFIED) :クライアントは、要求されたリソースの持つキャッシュされたバージョンを使用できます
クライアントエラー
- 401(UNAUTHORIZED) :匿名の要求が保護されたAPIにアクセスする
- 403(FORBIDDEN) :認証された要求が保護されたAPIにアクセスするための十分な権限を持っていない
- 404(見つからない) :リソースが見つかりません
- 409(CONFLICT) :競合しているリソース状態(たとえば、登録済みの電子メールでアカウントを作成しようとしているユーザー)
- 410(GONE) :404と同じですが、リソースが存在しました
- 412(PRECONDITION FAILED) :要求は、予期しない状態にあるリソースを変更しようとします。
- 422(UNPROCESSABLE ENTITY) :要求ペイロードは構文的には有効ですが、意味的に誤りがあります(例えば、評価されていない必須フィールド)
- 423(LOCKED) :リソースがロックされています
- 424(FAILED DEPENDENCY) :要求されたアクションは、失敗した別のアクション
- 429(大量のリクエストが多すぎます) :ユーザーが指定した時間内に多すぎるリクエストを送信しました
- それ以外の場合: 400(BAD REQUEST)
サーバーエラー
- 501(実装されていない) :サーバーは要求を満たすのに必要な機能をサポートしていません
- 503(SERVICE UNAVAILABLE) :一時的な過負荷または定期的なメンテナンスのために現在サーバーが要求を処理できません
- 507(INSUFFICIENT STORAGE) :サーバーは要求を正常に完了するのに必要な表現を格納できません
- それ以外の場合: 500(内部サーバーエラー)
ノート
誤った返答に身体を追加することを止めるものはありません。たとえば、 422(UNPROCESSABLE ENTITY)は少し曖昧です。応答本体は、エンティティを処理できなかった理由を示す必要があります。
嫌悪
各リソースは、それがリンクされているリソースにハイパーメディアを提供する必要があります。リンクは、少なくとも以下によって構成されます。
-
rel
( 相対エーションのため、名前別名は):メインリソースとリンク1(S)との関係を説明します -
href
:リンクされたリソースをターゲットとするURL
非推奨、コンテンツネゴシエーションなどを支援するために、追加の属性を使用することもできます。
Cormac Mulhallは 、クライアントが何をしようとしているかに基づいて、使用するHTTP動詞を決定する必要があると 説明しています 。疑わしいときは、APIドキュメントは、すべてのハイパーメディアとの利用可能なやりとりを理解するのに役立つはずです。
メディアの種類
メディアタイプは自己記述的なメッセージを持つのに役立ちます。クライアントとサーバーの間で契約の一部を果たし、リソースとハイパーメディアを交換することができます。
application/json
とapplication/xml
は非常にポピュラーなメディアタイプですが、多くのセマンティクスは含まれていません。それらは、ドキュメントで使用されている全体的な構文を記述するだけです。より特殊なメディアタイプHATEOAS要件は使用(又はを通して拡張されるべきサポートベンダーのメディアタイプのような)
クライアントは、要求にAccept
ヘッダを追加することによって、どのメディアタイプを理解するかをサーバに通知します。
Accept: application/hal+json
サーバーがそのような表現で要求されたリソースを生成できない場合は、 406(NOT ACCEPTABLE)を返します。それ以外の場合は、表現されたリソースを保持しているレスポンスのContent-Type
ヘッダーにメディアタイプを追加します。
Content-Type: application/hal+json
ステートレス>ステートフル
どうして?
ステートフルなサーバーとは、クライアントセッションがサーバーインスタンスのローカルストレージ(ほとんどの場合、Webサーバーセッション)に格納されていることを意味します。これは、しようとするときに問題があることを開始し、水平スケール :あなたはロードバランサの背後にあるいくつかのサーバインスタンスを非表示にした場合、サインイン時に1つのクライアントは、最初のインスタンス#1に派遣されている場合が、その後インスタンス#2に例えば保護されたリソースを取得するときクライアントセッションはインスタンス#1にローカルに格納されているため、2番目のインスタンスは匿名のものとして要求を処理します 。
セッションのレプリケーションやスティッキーセッションを設定するなどして、この問題に対処するソリューションが見つかっていますが、RESTアーキテクチャでは別のアプローチが提案されています。サーバーをステートフルにしてステートレスにしないでください。 フィールディングによれば、
クライアントからサーバーへの各要求には、要求を理解するために必要なすべての情報が含まれていなければならず、サーバー上の格納されたコンテキストを利用することはできません。 したがって、セッション状態はクライアント上で完全に保持されます。
つまり、要求がインスタンス#1またはインスタンス#2にディスパッチされているかどうかにかかわらず、要求はまったく同じ方法で処理する必要があります。このため、ステートレスアプリケーションは拡張しやすくなります。
どうやって?
一般的なアプローチは、 トークンベースの認証 、特にトレンディなJSON Webトークンによるものです。 JWTにはまだいくつかの問題があることに注意してください。特に、有効期限の 無効化と自動延長 (つまり、 私の機能を思い出してください )に関してです。
サイドノート
クッキーやヘッダー(または何か他のもの)を使用することは、サーバーがステートフルかステートレスかどうかに関係なく、トークン(ステートフルサーバー、JWTなどのセッションID)の転送に使用されるメディアです。
RESTful APIがブラウザでのみ使用される場合、( HttpOnlyで安全な )Cookieは、ブラウザが自動的に発信リクエストに添付するので便利です。 クッキーを選択した場合は、 CSRFを知っておく必要 があります(クッキーとカスタムHTTPヘッダーの両方で同じ固有の秘密値をクライアントに生成させて送信させることができます )。
条件付き要求を伴うキャッシュ可能なAPI
Last-Modified
ヘッダーを使用する
サーバーは、キャッシュ可能なリソースを保持するレスポンスにLast-Modified
日付ヘッダーを提供できます。クライアントは、この日付をリソースと共に保存する必要があります。
クライアントがリソースを読み取るようにAPIを要求するたびに、受信し保存した最新のLast-Modified
日付を含むIf-Modified-Since
ヘッダーを要求に追加できます。サーバーは、要求のヘッダーとリソースの実際の最後に変更された日付を比較する必要があります。等しい場合、サーバーは空の本文を持つ304(NOT MODIFIED)を返します。要求しているクライアントは、現在キャッシュされているリソースを使用する必要があります。
また、クライアントがリソースを更新するためにAPIを要求すると(つまり、安全でない動詞で)、 If-Unmodified-Since
ヘッダーを追加できます。これは競合条件の処理に役立ちます。ヘッダーと実際の最終変更日が異なる場合、サーバーは412(PRECONDITION FAILED)を返します。クライアントは、リソースの新しい状態を読み取ってから、リソースの変更を再試行する必要があります。
ETag
ヘッダーを使用する
ETag (エンティティタグ)は、リソースの特定の状態の識別子です。これには、 強力な検証のためのリソースのMD5ハッシュ、または弱い検証のためのドメイン固有の識別子があります。
基本的には、プロセスはLast-Modified
ヘッダーと同じです。サーバーはキャッシュ可能なリソースを保持するレスポンスにETag
ヘッダーを提供し、クライアントはこの識別子をリソースとともに格納します。
次に、受信した最新のETagを含むリソースを読み込みたいときに、クライアントはIf-None-Match
ヘッダーを提供します。ヘッダーが実際のリソースのETagと一致する場合、サーバーは304(NOT MODIFIED)を返すようになりました。
ここでも、クライアントはリソースを変更するときにIf-Match
ヘッダを提供することができ、提供されたETagが実際のものと一致しない場合、サーバは412(PRECONDITION FAILED)を返さなければならない。
その他の注意事項
ETag>日付
クライアントが要求に日付とETagの両方を提供する場合は、日付を無視する必要があります。 RFC 7232( こことここ )から:
受信者は、
If-Modified-Since
/If-Unmodified-Since
無視しなければならない(MUST)。要求にIf-None-Match
/If-Match
ヘッダーフィールドが含まれているIf-None-Match
。If-None-Match
/If-Match
の条件は、If-Modified-Since
/If-Unmodified-Since
の条件のより正確な置き換えIf-Unmodified-Since
なされ、2つは古い媒介との相互運用のためにのみ結合されますIf-None-Match
/If-Match
実装していない可能性があります。
浅いETags
また、 最後に変更された日付がリソースサーバー側と一緒に保持されることは明白ですが、ETagではいくつかの方法が利用できます。
通常の方法は、浅いETagを実装することです:サーバは条件付きヘッダが与えられていないかのようにリクエストを処理しますが、最後に返すレスポンスのETagを生成して(例えばハッシュすることによって)、比較します提供されたものと一緒に。これは、HTTPインターセプタだけが必要である(そして多くの実装がすでにサーバに依存しているため)実装が比較的容易です。つまり、この方法では帯域幅は節約できますが、サーバーのパフォーマンスは節約できます 。
ETagメカニズムのより深い実装は、潜在的には、キャッシュからのいくつかの要求を処理し、計算を全く行う必要がないなど、より大きな利点を提供する可能性がありますが、実装は、シンプルではなく、ここで説明します。
共通の落とし穴
なぜ動詞をURLに入れてはいけないのですか?
HTTPはRPCではありません : HTTPと RPCとが大きく異なるのは、リクエストがリソースに送られるということです 。結局のところ、URLはUniform Resource Locatorの略で、URLは Uniform Resource IdenfitierのURIです。 URLは対処したいリソースをターゲットにしています.HTTPメソッドは、 そのリソースで 何をしたいのかを示します 。 HTTPメソッドは動詞としても知られています 。つまり、URLの動詞は意味をなさないものです。 HATEOAS関係には動詞も含まれていてはならないことに注意してください。
部分的にリソースを更新する方法
更新された値でリソース全体を送信するようにPUT
リクエストがクライアントに要求するので、 PUT /users/123
を使用して、たとえばユーザーの電子メールを単純に更新することはできません。ウィリアム・デュランが説明したように。馬鹿のようにパッチしないでください。いくつかのREST準拠のソリューションが利用可能です:
- リソースのプロパティを公開し、更新された値を送信するために
PUT
メソッドを使用しますPUT
仕様では、個別に識別されたリソースをより大きなリソースの一部と重なる状態でターゲット設定することによって、
PUT https://example.com/api/v1.2/users/123/email
body:
new.email@example.com
- リソースをどのように変更する必要があるかを記述する一連の指示を含む
PATCH
要求を使用します( JSONパッチなど )。
PATCH https://example.com/api/v1.2/users/123
body:
[
{ "op": "replace", "path": "/email", "value": "new.email@example.com" }
]
- Matt Chapmanのコメントで提案されているように、リソースの部分表現を含む
PATCH
要求を使用しPATCH
。
PATCH https://example.com/api/v1.2/users/123
body:
{
"email": "new.email@example.com"
}
CRUD操作の世界に適合しないアクションはどうですか?
実用的なRESTful APIを設計するためのベストプラクティスで Vinay Sahniを引用:
これは物事が曖昧になることができる場所です。いくつかのアプローチがあります。
リソースのフィールドのように見えるようにアクションを再構成します。これは、アクションがパラメータを取らない場合に機能します。例えば、 活性化動作はブール
activated
フィールドにマッピングされ、PATCHを介してリソースに更新される。RESTfulな原則を持つサブリソースのように扱います。たとえば、GitHubのAPIを使用すると、
PUT /gists/:id/star
gistsDELETE /gists/:id/star
PUT /gists/:id/star
を付け 、DELETE /gists/:id/star
gistsPUT /gists/:id/star
を使用してスターをスタートすることができます。場合によっては、実際にはRESTfulな構造にアクションをマップする方法がありません。たとえば、マルチ・リソース検索は、特定のリソースのエンドポイントに適用する意味がありません。この場合、
/search
はリソースではないにもかかわらず最も意味を持ちます。これは問題ありません。APIコンシューマーの観点から正しいことを行い、混乱を避けるために明確に文書化されていることを確認してください。
一般的な実践
APIが文書化されています。 SwaggerやSpring REST Docsなど、ドキュメントを構築するためのツールが用意されています。
APIはヘッダーまたはURLを介してバージョン管理されます。
https://example.com/api/v1.2/blogs/123/articles
^^^^
- リソースには複数の名前があります 。
https://example.com/api/v1.2/blogs/123/articles
^^^^^ ^^^^^^^^
- URLはケブブケースを使用します(単語は小文字とダッシュで区切られます)。
https://example.com/api/v1.2/quotation-requests
^^^^^^^^^^^^^^^^^^
- HATEOASは、自分自身をターゲットとするリソースへの「自己」リンクを提供します:
{
...,
_links: {
...,
self: { href: "https://example.com/api/v1.2/blogs/123/articles/789" }
^^^^
}
}
- HATEOASの関係ではlowerCamelCaseを使用しています(最初のものを除いて小文字にしてから大文字にし、スペースは省略します)。JavaScriptクライアントがリンクにアクセスする際にJavaScriptの命名規則を尊重しながらドット表記を使用できるようにします。
{
...,
_links: {
...,
firstPage: { "href": "https://example.com/api/v1.2/blogs/123/articles?pageIndex=1&pageSize=25" }
^^^^^^^^^
}
}
RESTful HTTP APIによるブログ管理
次の例では、 HALを使用してHATOASを表現し、
ブログを入手する123
要求
GET https://example.com/api/v1.2/blogs/123
headers:
Accept: application/hal+json
応答
status: 200 (OK)
headers:
Content-Type: application/hal+json
body:
{
"id": 123,
"title": "The blog title",
"description": "The blog description",
"_links": {
"curies": [{ "name": "doc", "href": "https://example.com/docs/{rel}", "templated": true }],
"self": { "href": "https://example.com/api/v1.2/blogs/123" },
"doc:articles": { "href": "https://example.com/api/v1.2/blogs/123/articles{?pageIndex,pageSize}", "templated": true }
}
}
ブログで新しい記事を作成する123
要求
POST https://example.com/api/v1.2/blogs/123/articles
headers:
Content-Type: application/json
Accept: application/hal+json
X-Access-Token: XYZ
body:
{
"title": "The title 2",
"content": "The content 2"
}
応答
status: 201 (CREATED)
headers:
Content-Type: application/hal+json
body:
{
"id": 789,
"title": "The title 2",
"content": "The content 2",
"_links": {
"curies": [{ "name": "doc", "href": "https://example.com/docs/{rel}", "templated": true }],
"self": { "href": "https://example.com/api/v1.2/blogs/123/articles/789" },
"doc:blog": { "href": "https://example.com/api/v1.2/blogs/123", "title": "The blog title" },
"doc:comments": { "href": "https://example.com/api/v1.2/blogs/123/articles/789/comments{?pageIndex,pageSize}", "templated": true }
}
}
ブログ123の記事を入手する
要求
GET https://example.com/api/v1.2/blogs/123/articles/789
headers:
Accept: application/hal+json
応答
status: 200 (OK)
headers:
Content-Type: application/hal+json
body:
{
"id": 789,
"title": "The title 2",
"content": "The content 2",
"_links": {
"curies": [{ "name": "doc", "href": "https://example.com/docs/{rel}", "templated": true }],
"self": { "href": "https://example.com/api/v1.2/blogs/123/articles/789" },
"doc:blog": { "href": "https://example.com/api/v1.2/blogs/123", "title": "The blog title" },
"doc:comments": { "href": "https://example.com/api/v1.2/blogs/123/articles/789/comments{?pageIndex,pageSize}", "templated": true }
}
}
ブログ123の25件の記事の4ページ目を取得する
要求
GET https://example.com/api/v1.2/blogs/123/articles?pageIndex=4&pageSize=25
headers:
Accept: application/hal+json
応答
status: 200 (OK)
headers:
Content-Type: application/hal+json
body:
{
"pageIndex": 4,
"pageSize": 25,
"totalPages": 26,
"totalArticles": 648,
"_link": {
"firstPage": { "href": "https://example.com/api/v1.2/blogs/123/articles?pageIndex=1&pageSize=25" },
"previousPage": { "href": "https://example.com/api/v1.2/blogs/123/articles?pageIndex=3&pageSize=25" },
"self": { "href": "https://example.com/api/v1.2/blogs/123/articles?pageIndex=4&pageSize=25" },
"nextPage": { "href": "https://example.com/api/v1.2/blogs/123/articles?pageIndex=5&pageSize=25" },
"lastPage": { "href": "https://example.com/api/v1.2/blogs/123/articles?pageIndex=26&pageSize=25" }
},
"_embedded": [
{
...
}, {
"id": 456,
"title": "The title 1",
"content": "The content 1",
"_links": {
"curies": [{ "name": "doc", "href": "https://example.com/docs/{rel}", "templated": true }],
"self": { "href": "https://example.com/api/v1.2/blogs/123/articles/456" },
"doc:blog": { "href": "https://example.com/api/v1.2/blogs/123", "title": "The blog title" },
"doc:comments": { "href": "https://example.com/api/v1.2/blogs/123/articles/456/comments{?pageIndex,pageSize}", "templated": true }
}
}, {
"id": 789,
"title": "The title 2",
"content": "The content 2",
"_links": {
"curies": [{ "name": "doc", "href": "https://example.com/docs/{rel}", "templated": true }],
"self": { "href": "https://example.com/api/v1.2/blogs/123/articles/789" },
"doc:blog": { "href": "https://example.com/api/v1.2/blogs/123", "title": "The blog title" },
"doc:comments": { "href": "https://example.com/api/v1.2/blogs/123/articles/789/comments{?pageIndex,pageSize}", "templated": true }
}
}, {
...
}
]
}
ブログ123の記事789を更新
要求
PUT https://example.com/api/v1.2/blogs/123/articles/789
headers:
Content-Type: application/json
Accept: application/hal+json
X-Access-Token: XYZ
body:
{
"id": 789,
"title": "The title 2 updated",
"content": "The content 2 updated"
}
応答
status: 200 (OK)
headers:
Content-Type: application/hal+json
body:
{
"id": 789,
"title": "The title 2 updated",
"content": "The content 2 updated",
"_links": {
"curies": [{ "name": "doc", "href": "https://example.com/docs/{rel}", "templated": true }],
"self": { "href": "https://example.com/api/v1.2/blogs/123/articles/789" },
"doc:blog": { "href": "https://example.com/api/v1.2/blogs/123", "title": "The blog title" },
"doc:comments": { "href": "https://example.com/api/v1.2/blogs/123/articles/789/comments{?pageIndex,pageSize}", "templated": true }
}
}
ノート
- 更新するリソースを識別するために使用される識別子は、URL内の識別子です。本文内の識別子(存在する場合)は暗黙に無視する必要があります。
-
PUT
リクエストはリソース全体を更新するため、送信されるcontent
がない場合は、永続リソースから削除されているはずです。
ブログ123の記事789を削除
要求
DELETE https://example.com/api/v1.2/blogs/123/articles/789
headers:
Accept: application/hal+json
X-Access-Token: XYZ
応答
status: 204 (NO CONTENT)
headers:
Content-Type: application/hal+json
body:
{
"_links": {
"curies": [{ "name": "doc", "href": "https://example.com/docs/{rel}", "templated": true }],
"doc:blog": { "href": "https://example.com/api/v1.2/blogs/123", "title": "The blog title" }
}
}
REST違反
<stock>
<add>
<item>
<name>Milk</name>
<quantity>2</quantity>
</item>
</add>
</stock>
この本体を/stocks/123
ようなリソースに置くと、RESTの背後にある考え方に違反します。このボディはput
れ、必要なすべての情報が含まれていますが、ボディの処理時add
どこかにadd
するメソッド呼び出しもあります。 RESTに続いて、そのitem
を/stocks/123/items/
投稿しitem
。