NHN Cloud Meetup 編集部
REST APIを正しく理解して使用する
2019.06.24
66,119
ある日、友人から電話があり「REST APIって何?」という質問を受けましたが、「それはRESTにクライアントとサーバー間でデータを送受信する方式のことだよ」といった程度で思うように説明できませんでした。実際にREST APIのサービスを開発した経験もありますが、いざ説明しようとすると難しいですね。そこで今回、REST APIについて整理してみました。基本的なREST APIのほか、REST APIを設計する際に参考すべきいくつかのTipsを共有したいと思います。
1. REST APIの誕生
RESTはRepresentational State Transferという用語の略で、2000年にロイ・フィールディング(Roy Fielding)の博士論文で初めて紹介されました。ロイ・フィールディングは、HTTPの主な著者の一人で、Web(HTTP)の設計の優秀さに比べて適切に使用されていない様子を残念に思い、Webの利点を最大限に活用できるアーキテクチャとしてRESTを発表したそうです。
2. REST構成
簡単に言うとREST APIは次のように構成されています。詳細は後述します。
- 資源(RESOURCE) – URI
- 行為(Verb) – HTTPメソッド
- 表現(Representations)
3. RESTの特徴
1)Uniform(ユニフォーム・インターフェース)
Uniform Interfaceは、URIで指定されたリソースへの操作を統一して、限定的なインタフェースで実行するアーキテクチャスタイルを指します。
2)Stateless(ステートレス)
RESTはステートレスの属性を持ちます。言い換えると、作業の状態情報を別途保存して管理することはしません。セッション情報やCookie情報を保存して管理していないため、APIサーバーは受信したリクエストだけを単純に処理すればよいでしょう。これによってサービスの自由度が高くなり、サーバーで不要な情報を管理しないことから、実装が簡単になります。
3)Cacheable(キャッシュ可能)
RESTの最大の特徴の1つは、HTTPという既存のWeb標準をそのまま使用して、Web上で使用する既存のインフラをそのまま活用できるということです。したがってHTTPが持つキャッシュが適用できます。HTTPプロトコル標準で使用するLast-ModifiedタグやE-Tagを使うと、キャッシュの実装が可能です。
4)Self-descriptiveness(自己表現構造)
REST APIメッセージだけ見ても簡単に理解できる独自の表現構造になっています。これはRESTのもう1つの大きな特徴です。
5)Client – Server構造
RESTサーバーはAPIを提供し、クライアントはユーザー認証やコンテキスト(セッション、ログイン情報)などを直接管理する構造になっています。それぞれの役割が確実に区別されており、このため、クライアントとサーバーで開発すべき内容が明確になり、相互依存関係が低減されます。
6)階層型構造
RESTサーバーは複数レイヤで構成され、セキュリティ、負荷分散、暗号化レイヤなどを追加できる柔軟性のある構造になっています。プロキシ、ゲートウェイなどのネットワーク基盤の中間媒体を使用できます。
4. REST APIの設計ガイド
REST API設計時、最も重要な項目は、次の2つに要約できます。
1. URIは情報の資源を表現しなければならない。
2. 資源の行為は、HTTPメソッド(GET、POST、PUT、DELETE)で表現する。
他はすべて忘れても、これだけは必ず覚えておきましょう。
4-1. REST APIの規則
1)URIはリソースを表現しなければならない(リソース名は動詞ではなく、名詞を使用)
GET /members/delete/1
上記のような方式は、RESTを正しく適用していないURIです。URIはリソースを表現することに重点を置きましょう。deleteのような操作の表現が入ってはいけません。
2)リソースの操作は、HTTPメソッド(GET、POST、PUT、DELETEなど)で表現する
上記の誤ったURIをHTTPメソッドで変更すると、こうなるでしょう。
DELETE /members/1
会員情報を読み込む際はGET、会員情報を追加したい場合はPOSTメソッドを使って表現します。
会員情報の取得
GET /members/show/1 (x) GET /members/1 (o)
会員情報の追加
GET /members/insert/2 (x) - GETメソッドはリソースの生成に適さない。 POST /members/2 (o)
[参考] HTTPメソッドの適切な役割
POST、GET、PUT、DELETE、4つのメソッドを持ってCRUDできます。
メソッド | 役割 |
---|---|
POST | 対応するURIをリクエストし、リソースを作成する |
GET | リソースを照会して、当該ドキュメントの詳細情報を取得する |
PUT | 当該リソースを変更する |
DELETE | リソースを削除する |
URIはリソースの表現に集中して、操作の定義はHTTPメソッドを使って処理するのが、REST APIの規則です。
4-2. URI設計時の注意点
1)スラッシュ区切り記号(/)は、階層関係を表すのに使用する
http://restapi.example.com/houses/apartments http://restapi.example.com/animals/mammals/whales
2)URIの最後の文字にスラッシュ(/)を含めない
URIに含まれるすべての文字は、リソースの唯一の識別子として使用します。URIが異なるということは、リソースが異なるということであり、逆にリソースが異なると、URIも変わらなければなりません。REST APIは、明確なURIを作成して通信する必要があるため、混同しないようにURIパスの最後に、スラッシュ(/)を使用していけません。
http://restapi.example.com/houses/apartments/ (X) http://restapi.example.com/houses/apartments (0)
3)ハイフン( – )は、URI可読性を高めるために使用
URIを簡単に読み取って解釈できるように、止むを得ず長いURIパスを使用する場合は、ハイフンを使って可読性を高めます。
4)アンダースコア(_)は、URIに使用しない
フォントによっても異なりますが、下線は表示が難しい、または下線によって文字が隠れたりすることがあるため、このような問題を回避するために、アンダースコアの代わりにハイフン( – )の使用を推奨します。
5)URIパスは小文字が適している
URIパスに大文字を使うのは避けましょう。大文字と小文字に基づいて別のリソースとして認識してしまうためです。RFC 3986(URI文法形式)は、URIスキームとホストを除き、大文字と小文字を区別するように規定しています。
RFC 3986 is the URI (Unified Resource Identifier) Syntax document
6)ファイルの拡張子は、URIに含めない
http://restapi.example.com/members/soccer/345/photo.jpg (X)
REST APIは、メッセージ内容のフォーマットを表すファイルの拡張子をURIの中に含めません。Accept headerを使いましょう。
GET / members/soccer/345/photo HTTP/1.1 Host: restapi.example.com Accept: image/jpg
4-3. リソース間の関係を表現する方法
RESTリソース間には関連性がある可能性があり、このような場合は、次のような表現方法を用います。
/リソース名/リソースID/関係する他のリソース名 ex) GET : /users/{userid}/devices (一般的に所有する'has'の関係を表現するとき)
関係性が複雑なときは、サブリソースとして明示的に表現する方法があります。例えば、ユーザーが「好きな」デバイスのリストを表現したい場合、次のような形で使用できます。
GET : /users/{userid}/likes/devices (関係性が曖昧で具体的な表現が必要なとき)
4-4. 資源を表現するCollectionとDocument
CollectionとDocumentについて理解すると、URI設計が一層簡単になります。ドキュメントは、単純に文書として理解してもよいし、1つのオブジェクトと理解してもよいでしょう。コレクションは、文書の集合、オブジェクトの集合だと考えましょう。コレクションとドキュメントはすべてのリソースと表現ができ、URIに表現されます。例を見てみましょう。
http:// restapi.example.com/sports/soccer
上記を見ると、sportsというコレクションと、soccerというドキュメントで表現されています。さらにこのようにすると、
http:// restapi.example.com/sports/soccer/players/13
sports、playersコレクションやsoccer 13(13番の選手)を意味するドキュメントでURIが行われるようになります。ここで重要なのは、複数のコレクションを使用しているという点です。より直感的なREST APIにするには、コレクションとドキュメントを使用するときに、単数、複数も遵守すると、さらに理解しやすいURIを設計できるでしょう。
5. HTTPステータスコード
最後に、ステータスコードを簡単に見てみましょう。うまく設計されたREST APIは、URIのみならず、そのリソースに対する応答まで含めて、うまく設計されています。正確なステータスコードだけでも多くの情報を伝えられるので、ステータスコードの値を正しく返すことは、とても重要です。200や4XX関連の特定コード程度を使っている場合は、より正確なステータスコードの値を使用することを推奨します。
ステータスコードについては、いくつかのポイントだけ整理します。
ステータスコード | 内容 |
---|---|
200 | クライアントのリクエストを正常に遂行 |
201 | クライアントがリソースの生成をリクエストし、当該リソースが正常に生成される(POSTによるリソース生成時) |
ステータスコード | 内容 |
---|---|
400 | クライアントのリクエストが不十分な場合に使用するコード |
401 | クライアントが認証されていない状態で保護されたリソースをリクエストしたときに使用するコード |
403 | ユーザー認証の状態に関わらず、応答したくないリソースをクライアントがリクエストしたときに使用するコード (403より400や404の使用を推奨。403自体がリソースが存在するという意味であるため) |
405 | クライアントがリクエストしたリソースが、使用できないメソッドを用いた場合に使用するコード |
ステータスコード | 内容 |
---|---|
301 | クライアントがリクエストしたリソースのURIが変更されたときに使用するコード (応答時、Location headerに変更されたURIを書かなければならない) |
500 | サーバーに問題がある場合に使用するコード |
おわりに
RESTFulなAPIを設計するときに役立ちそうな内容をまとめてみました。整理しながら改めて感じたことは、正確に理解しなければ「説明できない」ということです。これからも新しい知識を学習して、実務で利用する際、「適当」ではなく「正しい理解」をもとに、問題を解決していくように肝に銘じたいと思います。
最後に、REST APIは定められた明確な基準がないため、REST APIを使用する際は「何が正しいか、正しくないか」ではなく、開発するサービスの特徴とそのサービスを利用するユーザー像を十分に考慮して設計するようにしましょう。