読書研修ーWebを支える技術　第15章読み取り専用のWebサービスの設計

## リソース設計とは何か
リソース設計とは、クライアントとサーバの間のインタフエースの設計、つまり Web サービスやWeb APIの外部設計です。
どのようにリソースを分割し、URIで名前を付け、相互にリンクを持たせるかが設計します。

## リソース指向アーキテクチャのアプローチ
<strong>１．Webサービスで提供するデータを特定する</strong>
<strong>２．データをリソースに分ける</strong>
<dd>そして、各リソースに対して次の作業を行います。</dd>

<strong>３．リソースにURIで名前を付ける</strong>
<strong>４．クライアントに提供するリソースの表現を設計する</strong>
<strong>５．リンクとフオームを利用してリソース同士を結び付ける</strong>
<strong>６．イベントの標準的なコースを検討する</strong>
<strong>７．エラーについて検討する</strong>
## 郵便番号検索サ-ビスの設計
郵便番号検索サ-ビスの要件は次の通りです。
* 日本の郵便番号情報を提供する
    * 郵便番号情報は、郵便番号、住所、住所の読みから成る
    * 住所は、都道府県名、市区町村名、町域名から成る
* 郵便番号の前方一致で、郵便番号情報を検索できる
* 住所および住所の読みで、郵便番号情報を全文検索できる
* データはすべて読み取り専用である
### Webサービスで提供するデータを特定する
日本郵便が公開している郵便番号のCSVデータをもとにし、CSVデ-タには1行に1つの郵便番号のデータが入っています。1行の各カラムには郵便番号とその住所のデータが入っています。
| カラム番号| データ名 |データ型 |
|:-:|:-:|:-:|
| 3 | 郵便番号(7桁)  |  半角数字 |
| 4 |  都道府県名 |  半角カタカナ |
| 5 | 市区町村名  |  半角カタカナ |
| 6 |  町域名 | 半角カタカナ  |
| 7 |  都道府県名 |  漢字 |
| 8 | 市区町村名  |  漢字 |
| 9 |  町域名 | 漢字  |

このサービスは次の３つデータを持っている
* 7桁の郵便番号
* その郵便番号が表現する住所(都道府県名、市町村名、町域名)
* 住所のカタカナ読み



### データをリソースに分ける
このWebサービスで提供するリソースをまとめると、次の4種類です。
* 郵便番号リソース
    * 1つの郵便番号に対応するリソース。 その郵便番号の住所や読みも入っている
* 検索結果リソース
    * 郵便番号の一部や住所の一部で郵便番号を検索した結果のリソース
* 地域リソース
    * 都道府県、市区町村、町域のリソース。上位の地域は、下位の地域の情報を含んでいる
* トップレベルリソース
    * このWebサ-ビスのスタート地点。都道府県リソースへのリンクと、検素フオームを含んでいる
通常はこのステップを何回か繰り返し行い、最適なリソ-ス分割を求めます。
## リソースにURIで名前を付ける
各リソースに対してURIで名前を付けていきます。
### 郵便番号リソース
まず郵便番号リソースのURIを考えましょう。郵便番号リソースは郵便番号で一意に識別できるので、URIには郵便番号を使うのが良さそうです。「-」はURIで使える文字列ですけど、それぞれの形式の利点と欠点は次のとおりです。
| 形式 | 利点| 欠点 |
|:-:|:-|:-|
| 「-」なし(1120002)  | １．プログラムで扱いやすい<br>２．短い  |  人間にとって読みづらい |
| 「-」あり(112-0002)  |  人間にとって読みやすい |  １．プログラムで「-」の位置を気にしなければならない <br>２．長い |

今回のシステムの用途(主にプログラム向けのWeb API)を考えると、プログラムから扱いやすいほうを正規のURI としたほうがよい、と判断したためです。「-」付きの代理リソ-スにアクセスした場合は301 Moved Permanentlyで「-」なしのURIにリダイレクトします。

### 検索結果リソ-ス
検索結果リソースは検索キーワードの入力を必要とします。一般にクライアントからの入力を受け取る場合はクエリパラメータを利用します。
例：`http://zip.ricollab.jp/search?q=小石川`
/search は検索クエリを受け取るリソースのURI です。このURI には検索クエリを表現する「q」というクエリパラメータが必ず付きます。
### 地域リソース
地域リソースは各都道府県や市区町村を表現するリソースです。地域リソスは階層を持っており、階層構造をURIで表現する場合は「/」を利用します。地域リソースのURIは`http://zip.ricollab.jp/{都道府県名}/{市区町村名}/{町域名}`になる。

### トップレベルリソース
トップレベルリースはこのWebサービスのスタート地点です。このようなリソースには通常一番ルートとなるURIを与えます。例：`http://zip.ricollab.jp`
## クライアントに提供するリソースの表現を設計する
1つのリソースが複数の表現形式をサポートしていると便利です。
今回は郵便番号検索サービスですので、マルチメディア表現は必要ありません。XMLと軽量フォーマットの表現を利用することにします。
<strong>Web上の代表的な表現形式</strong>
| 分類 | 表現形式 |
|:-:|:-|
| XML表現  |  XHTML<br>Atom<br>独自XML |
| 軽量フォーマット表現  |  JSON/JSONP<br>	YAML<br> CSV |
| マルチメディア表現  | 画像(GIF、JPEG、PNG)<br>映像(MPEG、WMV、MOV)<br>マルチベージ画像(PDF、TIFF)  |				
### XML表现
XMLはほとんどのプログラミング言語がデフォルトで処理系を用意しており、表現として採用するには最適なものの一つです。
* XHTML
    * XHTMLは基本的な文書構造を持ち、リンクやフォームといったハイパーメディアで必要となる機能を一通りそろえている。プラウザで表示できることも大きな特長。
    * microformatsを用いると文書構造以上の意味を持たせることもできる
* Atom 
    * Atom はプログや検素結果、ポッドキャストなどのリスト情報を表現するのに向いているフォーマットである。目的に応じて多様な拡張が存在することも大きな特長。
    * しかし、ID(`<id>` 要素)、タイトル(`<title>`要素)、著者(`<author>`要素)、更新日時(`<updated>`要素)が必須なので、著者や更新日時を持たないデータには適用しづらい

### 今回は、XML表現としてXHTMLを採用：
* 郵便番号データには、Atom で必須の著者や更新日時がない
* いずれにせよプラウザで表示するフォーマットも用意したい

### 軽量フォーマット表現
<strong>各軽量フォーマット表現の利点と欠点</strong>
| フォーマット | 利点 | 欠点 |
|:-:|:-|:-|
|  JSON |  JavaScriptとの相性抜群。<br>配列やハッシュなどのデータ構造もある。<br>文字エンコーディング固定 |  YAMLに比べて書きにくい  |
| YAML  |  書きやすい、読みやすい |  ライブラリ少ない |
|  CSV | 表形式のデータに最適。<br>読み込み可能なソフト多数  |  文字コードの扱いにくい。<br>エスケープ文字問題もある |

今回はJSONを選択した：
* JavaScriptがメインのクライアントになる可能性が高い
* クロスドメイン通信

### URIで表現を指定する
リソースの表現はリクエストのAcceptヘッダでも指定できるが、URIで指定できる。
XHTML表現には「.html」,JSON表現には「.json」という拡張子つける。

## リンクをフォームを利用してリソース同士を結びつける
![Screenshot from 2023-05-22 16-10-29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3330699/7707b7ec-d581-4e22-1b5a-86a300e00092.png)


## イベントの標準的なコースを検討する
この Web サービスの提供者側か想定する標準的な利用コースは次の3つです。
* 郵便番号を検索するコ-ス
①フォームに郵便番号を入力
②検素結果リソースを取得
③目的の郵便番号リソースを取得
* 住所から郵便番号を検索するコ-ス
①フォームに住所を入力
②検素結果リソースを取得(必要であれば)ページをめくる
③目的の郵便番号リソースを取得
* 地域リソースの階層をたどりながら郵便番号を選択するコース
①都道府県リソースを選択し市区町村一覧を表示
②巿区町村リソースを選択し町域一覧を表示
③町域リソースを選択し郵便番号一覧を表示
④目的の郵便番号リソースを取得
## エラーについて検討する
### 存在しないURIを指定した
これは最もよくあるエラーです。たとえば、 http://zip.ricollab.jp/1234567のような存在しないURIを指定した場合、404 Not Found返します。
### 必須パラメータを指定していない
検索結果リソースは必ずqというクエリパラメータを指定しているので、クライアント側の何らかのミスでこのパラメータが抜けてしまった場合は、400 Bad Requestを返す。
### サポートしないメソッドを使用した
今回設計したリソースはすべて読み取り専用ですので、GETとHEAD以外は受け付けません。
そのようなメソッドを指定した場合は405 Method Not Allowedを返します。