RESTful APIのURI設計(エンドポイント設計)


[RESTful APIのリソース設計](http://qiita.com/NagaokaKenichi/items/ef23ca15ba0e9e5ee022)で述べた通り、何をリソースとするかを決めたらそのリソースを識別するURIを検討する必要がある。

# エンドポイントとは何か

エンドポイントとはAPIにアクセスするためのURIのこと。例えば、QiitaのAPIで自分の情報を取得する時のエンドポイントは以下となる。
http://qiita.com/api/v2/users/nagaokakenichi

似たような言葉に「エントリポイント」というものがある。エントリポイントとはプログラムやサブルーチンの実行を開始する場所のこと。
Qiita視点で考えると、
http://qiita.com/api/v2/users/nagaokakenichi
を参照されることでプログラムが開始されるので、Qiitaからすると上記URIはエントリポイントとなる。
つまり、エンドポイントはAPIにアクセスする側からの、エントリポイントはアクセスされる側からの違いということになる。
※[エンドポイントとエントリーポイントの違い](http://memopct.blogspot.jp/2013/07/blog-post.html)


# URIの考え方

### URIの基本的な設計

良いURIの設計で重要な原則は、
　**覚えやすく、どんな機能を持つURIなのかがひと目でわかる**
ということ。
上記を意識することで、APIを利用する開発者がエンドポイントを間違ったり、利用方法を間違ったりする確率を下げることができる。結果として、APIを利用する開発者の生産性を向上させ、APIの評価を上げる効果があるとともに、間違ったアクセスが大量に行われてAPIを配信するサーバに負荷がかかってしまったりする問題も避けることができる。

### 一般的に良いとされるURIの重要な事項

##### 1. 短くて入力しやすい
短くて入力しやすいものはシンプルで覚えやすいことにつながる。長いURIは不要な情報が入っていたり、意味が重複していたりすることがある。

例えば、
　http://api.example.com/service/api/search
というURIは、「api」「search」という言葉があることから、何らかの検索用のAPIということは分かるが、「api」という言葉がホスト名とパスの両方に**重複**して含まれており、さらに「service」という類似した**不要**な言葉も含まれている。
これは、基本的に以下のようにより短いシンプルなURIで表現できる。
　http://api.example.com/search

同じことをしているなら、短くシンプルなほうが理解しやすく、覚えやすく、入力間違いも少なくできる。

##### 2. 人間が読んで理解できるURI
例えば、
　http://api.example.com/sv/u/
というURIは、「api」という言葉があるから何らかのAPIということは分かるが、「sv」「u」という言葉が何を意味しているのかが不明。短くしすぎて逆にわかりづらくなってしまっている。こうしたわかりづらいURIを生み出さないためにも、むやみに省略形を使わない。ただし、「jp」「jpn」等の国名コードのようなISOの国際規格として標準化されているようなものは、そちらを使った方がわかりやすい。また、利用する英単語も一般的によく使われているものが好ましい。

##### 3. 大文字小文字が混在していないURI
http://api.example.com/Users/12345
のように大文字と小文字を混在させると、わかりづらく間違えやすいURIとなってしまう。どちらかに統一した方がよく、その場合標準的に選択されているのは小文字となっている。

##### 4. サーバ側のアーキテクチャが反映されないURI
サーバ側のアーキテクチャとは、例えばどんなサーバソフトウェアを利用しているか、どんな言語を使って実装しているか、サーバのディレクトリ構成がどうなっているかということ。
例えば、
　http://api.example.com/cgi-bin/get_user.php?user=100
というURIは、PHPで書かれていてCGIとして動作していることが想像できる。APIの利用者にとってこういった情報は全く不要な情報である。ただし、こうした情報をもとに悪事を働かそうとする人たちにとっては重要な情報である。こうした情報をもとに攻撃を受ける可能性を下げるためにも、サーバ側のアーキテクチャが反映されているURIは避けるべきである。

##### 5. ルールが統一されたURI
ここでいうルールとは、利用する単語、URIの構造を意味している。APIを提供する場合、複数のエンドポイントを公開するのがほとんどで、1つのエンドポイント、1種類のルールで表せるエンドポイントだけですむケースというのは少ない。例えば、SNSで以下のような2つのエンドポイントがある場合、

　・友達情報の取得
　　　http://api.example.com/friends?id=100
　・友達へメッセージの投稿
　　　http://api.example.com/friend/100/message

上のほうは、friendsと複数形でIDはクエリパラメータで指定するようになっている。一方下の方は、friend、messageと単数形で、しかもIDはURIのパスに入れる形になっている。こうすると、統一感がなくバラバラで格好悪いだけでなく、APIを利用する場合に混乱を招きやすく、トラブルの温床につながる。そのため、以下のようにルールを統一しておいた方が好ましい。

　・友達情報の取得
　　　http://api.example.com/friends/100
　・友達へメッセージの投稿
　　　http://api.example.com/friends/100/messages

##### 6. バージョン番号が含まれたURI
APIは公開したらできる限り変更しないことが望ましいが、実際は変更を余儀なくされるケースも存在する。そうした際に、APIを利用しているクライアントに極力影響を与えないよう、新旧のAPIをそれぞれバージョン番号で管理しそれらを共存させながら、APIを利用しているクライアントが任意のタイミングで新バージョンに移行できるような状態にしておく。以下は著名なAPIのURI例。どれもバージョン番号が含まれている。

|サービス|URI|
|:--|:--|
|Twitter|https://api.twitter.com/1.1/|
|Qiita|http://qiita.com/api/v2/|
|Facebook Graph API|http://graph.facebook.com/v2.5|

# HTTPメソッドとURI
HTTPメソッドとエンドポイントは切っても切れない関係にある。URIがリソースを表すものだとすると、HTTPメソッドは操作(何をするか)を表すものである。1つのURIのエンドポイントに異なるメソッドでアクセスすることで、情報を取得するだけでなく情報を変更したり、削除したり等のさまざまな操作を行うようにすることで、リソースとそれをどう扱うかをきちんと分離して扱うことができる。これはHTTPメソッドの本来の考え方に合致しており、Web APIではこの考え方に沿って設計を行うことが主流となっている。各HTTPメソッドについては以下を参照。
[リソース指向アーキテクチャの統一インターフェース](http://qiita.com/NagaokaKenichi/items/0f3a55e422d5cc9f1b9c#%E7%B5%B1%E4%B8%80%E3%82%A4%E3%83%B3%E3%82%BF%E3%83%BC%E3%83%95%E3%82%A7%E3%83%BC%E3%82%B9)


# URI設計

### リソースにアクセスするためのURI設計の注意点

##### 1.複数形の名詞を利用する 
基本的にリソースは「集合」を表すものであるため、複数形の方が適切である。また、HTTPのURIはリソースを表現しているため、動詞ではなく名詞を利用するべきである。

##### 2.利用する単語に気をつける
例えば、「探す」という単語は「search」「find」等があるが、searchは探す場所を目的語にとり、findは探すものを目的語にとる。一般的にWeb APIでは「search」が利用されているので、「探す」という意味ではsearchが適切。もし迷うようなら、一般的にどのような単語が使われているかを[Programmable Web](http://www.programmableweb.com/apis)で探して検討してみると良い。

##### 3.スペースやエンコードを必要とする文字を使わない
URIで利用できない文字はパーセントエンコードされる。また、スペースはURI中では「+」に変換される。エンコードされたり+に変換されるとそのエンドポイントがどのようなものなのか一目で分からなくなってしまうので、スペースやエンコードを必要とする文字の利用は避けるべきである。

##### 4.単語をつなげる必要がある場合はハイフンを利用する 
2つ以上の単語をつなげる必要がある場合、以下のような方法がある。

|ケース|URI|
|:--|:--|
|スパイナルケース|http://api.example.com/v1/users/12345/profile-image|
|スネークケース|http://api.example.com/v1/users/12345/profile_image|お
|キャメルケース|http://api.example.com/v1/users/12345/profileImage|

公開されているAPIを見てもバラつきがあり、一般的にコレ、といったものが存在しない。そのため好みで決めてしまっても問題はない。ただ、URI中のドメイン名はハイフンは許可されているがアンダースコアは使えないため、迷ったらドメイン名と同じルールでURI全体を統一するためハイフンでつなげるのが望ましい。
※最も良いのは単語のつなぎ合わせを極力避け、users/profileのように区切る方が望ましい(URIとして見やすいので)。 

# 参考
[Web API: The Good Parts](https://www.oreilly.co.jp/books/9784873116860/)
[翻訳: WebAPI 設計のベストプラクティス](http://qiita.com/mserizawa/items/b833e407d89abd21ee72)