RestfulなWebAPIの設計

#RestfulなWebAPIとは何か
###RESTとは
>Representational State Transfer (REST) は、ウェブのような分散ハイパーメディアシステムのためのソフトウェアアーキテクチャのスタイルのひとつである。[wikipedia](https://ja.wikipedia.org/wiki/REST)

RESTの原則に従って実装されているシステムのことを、RESTfulと呼ぶようです。
そして、RESTの原則は以下の４つになります。

```
　・URIで公開されていること
　・HTTPメソッドを利用すること
　・ステートレスなこと
　・ハイパーメディア的な書式で情報を表現すること
```

###WebAPIとは
「HTTPプロトコルを利用してネットワーク越しに呼び出すAPI」のこと。簡単に言えばあるURIにアクセスすることでサーバ側の情報を更新したり、サーバ側に置かれた情報を取得したりするウェブシステムで、プログラムからアクセスしてそのデータを利用するためのもの。

#エンドポイントの設計
URI（Uniform Resource Identifier）とメソッドの関係は、「操作する対象（リソース）」と「何をするか」を表すものです。APIであればエンドポイントで取得できる情報がリソースであり、メソッドはそのリソースをどう操作するか表すものです。


| メソッド名        |説明               |
|:-----------------|:------------------|
| GET              |リソースの取得      |
| POST             |リソースの新規登録  |
| PUT              |リソースの更新      |
| DELET            |リソースの削除      |

他にもHEADやPATCHなどがありますが今回は説明を割愛します。

###■POSTメソッドとPUTメソッドの違い
POSTとPUTの違いは、新規登録かどうかです。対象のリソースが新規に登録される場合はPOSTを使用し、対象のリソースを更新する場合はPUTを利用するのがよさそう。

###■パスパラメータとクエリパラメータの使い分け
https://xxxxx/path/pathparameter?query=queryparameter
上記URLのpathparameterがパスパラメータ、queryparameterがクエリパラメータ

特定のリソースを識別するために必要なものはパスパラメータ
検索やフィルタやソートなどで必要になるパラメータはリクエストパラメータとするのが良いです。

###■大文字・小文字が混同しないURI
RFC3986にはschemeとhostは大文字と小文字を区別しなくても良いと定義されていますが、大文字小文字が混同していると読みずらいからやめましょうという話。ただし、エンドポイントとして統一されていればどちらでも良いと思います。

####どうしても単語を2つ以上繋げる場合
個人的にはキャメルケースが好きですけど、Google的にはスパイナルケースが推奨されています。どのケースを使うかは自由ですが、これもエンドポイントとして統一されていればどれでも良いと思います。

| ケース名          |例               |
|:-----------------|:----------------|
| キャメルケース    |userProfile      |
| スネークケース    |user_profile     |
| スパイナルケース  |user-profile     |

##レスポンスデータの設計

####ステータスコードでエラーを表現
RESTfulなWebAPIでは、処理結果をHTTPのステータスコードで表現するべきとされています。その理由としては、適切なステータスコードを返さない場合、エンティティの中身を見て結果を判断させなくてはいけなくなってしまうためです。

ステータスコードの詳細は割愛しますので以下のリンクで確認してください。
>ステータスコード一覧 (wikipedia)
https://ja.wikipedia.org/wiki/HTTP%E3%82%B9%E3%83%86%E3%83%BC%E3%82%BF%E3%82%B9%E3%82%B3%E3%83%BC%E3%83%89

普段よく使う押さえておきたいステータスコードはこのあたりではないでしょうか。

| ステータスコード       |処理               |
|:-----------------    |:------------------|
| 400 (Bad Request)    |バリデーションエラー |
| 401 (Unauthorized)   |認証エラー          |
| 403 (Forbidden)      |認可エラー          |
| 408 (Request Timeout)|タイムアウト     　　|
| 500 (Internal Server Error)|サーバ内部エラー|
| 503                  |メンテナンス|

##ヘッダの設計
代表的なヘッダを以下に記載する。詳細に知りたい人はRFC7321を確認してください。

| ヘッダ                   |種別                     |内容         　　                               |
|:-------------------------|:----------------------- |:---------------------------------------------|
| Accept                   |リクエストヘッダ         　|受信可能なレスポンスデータのコンテンツ対応を指定　|
| Content-Type             |エンティティヘッダ         |ボディのオブジェクトタイプ                      |
| Content-Length           |エンティティヘッダ         |ボディのサイズ                                 |
| cache-control            |一般ヘッダ                |キャッシュするかどうか                          |

**POSTの例**

```
[Request Header]
    Content-Type: application/json
    Accept: application/json
    cache-control: no-cache
    content-length: 20
[Response Header]
    Cache-Control: no-cache, no-store
    Pragma: no-cache
    Content-Type: application/json;charset=UTF-8
```

**GETの例**

```
[Request Header]
    Accept: application/json
    cache-control: no-cache
[Response Header]
    Cache-Control: no-cache, no-store
    Pragma: no-cache
    Content-Type: application/json;charset=UTF-8
```

#ユーザー一覧を取得するRestfulなWebAPIを設計してみる。
##リソースを考える
まず最初に考えることは「操作する対象（リソース）」と「何をするか」です。
ユーザ一覧を取得するAPIではリソースは「ユーザー」、何をするかは「参照する」になります。
##URLを設計する
###ディレクトリに分けるか、サブドメインで分けるか
　http://example.com/hoge
　http://hoge.example.com/
これもどちらでも良いですが、個人的にはサブドメインで分けるのが好きです。

###バージョンを含める。
　APIの仕様変更があった場合に、既存のクライアントに影響を与えないために、URLにバージョンを含めましょう。versionを表すvをつける場合や、小数まで記載するなど様々な書き方があります。個人的にはv付き整数が好きです。
　http://hoge.example.com/v1
　http://hoge.example.com/1
　http://hoge.example.com/v1.0.0

###動詞は使わないで複数形の名詞を使う。
　ダメな例：http://hoge.example.com/v1/getUser
　操作はHTTPメソッドで表すのでURIに動詞は含めないようにする。
　
　複数形の名詞で設計
　http://hoge.example.com/v1/users
　複数形の名詞で設計することでこのAPIはリソースとしてユーザー一覧を指している。
　
　個別のユーザーを取得するAPIの場合
　http://hoge.example.com/v1/users/{userid}
　ユーザー一覧の中の{userid}のユーザーを指す。

###HTTPメソッドを決める。
今回はリソースを考えるで「参照する」ときめていたのでGETになります。
　**GET http://hoge.example.com/v1/users**
ちなみにこのAPIが成功した場合はHTTPステータス200(OK)が返却されるように設計する。

###補足
ユーザー追加のRestfulなWebAPIを設計する場合、URIは**POST http://hoge.example.com/v1/users**とし、BODY部にユーザー情報などを含める設計にする。成功した場合のHTTPリクエストは200(OK)ではなく201(Created)を返却。

|WebAPI        　　　　|エンドポイント                            |HTTPメソッド|
|:--------------------|:----------------------------------------|:----------|
| ユーザー一覧取得     |http://hoge.example.com/v1/users         |GET         |
| ユーザー追加         |http://hoge.example.com/v1/users         |POST       |
| 特定ユーザーの情報取得|http://hoge.example.com/v1/users/{userid}|GET        |
| 特定ユーザの情報更新  |http://hoge.example.com/v1/users/{userid}|PUT        |
| ユーザの削除         |http://hoge.example.com/v1/users/{userid}|DELETE     |