# Webを支える技術 第2部 URI ## 第4章 URIの仕様 ### 4.1, 4.2 URIの重要性、URIの構文 #### 4.2.1 URIの基本 URIはリソースを統一的に識別するIDである。(単語の説明はWeb技術入門参照 [リンク](https://hackmd.io/MhFaz5FNQyGMBXtmb_iatw?view#22-Web%E3%82%92%E6%94%AF%E3%81%88%E3%82%8B%E6%8A%80%E8%A1%93%E3%81%AE%E7%99%BA%E6%98%8E)) 具体的には、**URIスキーム、ホスト名、パス**の3つに分かれる。 ユニークなホスト名+パスの階層構造指定により、必ずユニークなURLが作り出せる。 (例)http://www.example.jp/index.html の場合 * http:// :**URIスキーム**。URIが利用するプロトコルを指す。一般にhttpと、SSLにより暗号化されたURIを表すhttpsが用いられる。なお、区切りは://となる。 * www.example.jp :**ホスト名**。原則としてIPアドレスが入るが、多くの場合はドメイン名が設定され、DNSサーバへの問い合わせを経てアクセスが可能となる。なお、ホスト名はインターネット上でユニークな値である必要がある。 * /index.html :**パス**。html等のファイルが格納されているパスを示す。最初の/は任意のベースURIとなり、それ以降のパスを指定する。 #### 4.2.2複雑なURI 以上の3つの要素以外にも要素を加えた複雑なURIも作成できる。 (例)http://yuuki:pass@blog.example.jp:8000/index.html?q=test&debug=true#n10 の場合 * yuuki:pass@ :**ユーザ情報**。この場合ユーザ名とパスワードが入っている。通常はセキュリティ上の観点でユーザ情報は表示しない。(POSTメソッドの利用など) * :8000 :**ポート番号**。アクセスするポート番号を表す。ローカルサーバを表す特別なドメイン名であるlocalhostと組み合わせて使う場面が多い。 * ?q=test&debug=true :**クエリパラメータ**。リクエストパラメータを送信した結果を表すページ等で表示される。**クライアントの入力値に応じた動的なURI生成**が行われる。 * #n10 :**URIフラグメント**。HTMLのページ数等、URIのリソース内部でさらに細かい部分を指定する際につけられる。 ### 4.3 絶対URIと相対URI リソースのパス指定がフルパス指定のものを**絶対URI**、ある位置から見たパス指定のものを**相対URI**という。 相対URIは「ある位置」の指定が必要である。この「ある位置」にあたるURIのことを**ベースURI**という。 ベースURIの指定は初めのリソースのURIを指定する方法もあるが、クライアント側での保存が必要で実現が難しい。 そこで**HTMLの中に明示的に示しておく**方法が用いられる。HTMLの場合、ヘッダ部分に<base>要素を追加して指定する。 ### 4.4 URIと文字 URIに利用できるのは、半角英数字及び一部記号のみである。(ASCII文字) これ以外の文字を入力すると文字化けとなるため、URIでは **%エンコーディング** を行う。(%エンコーディングの仕組みについてはWeb技術入門を参照 [リンク](https://hackmd.io/MhFaz5FNQyGMBXtmb_iatw?view#343-%E6%96%87%E5%AD%97%E5%8C%96%E3%81%91%E3%81%A8%E3%82%A8%E3%83%B3%E3%82%B3%E3%83%BC%E3%83%89)) なお、文字形式によってエンコーディング結果は異なる。(UTF-8の場合、全角ひらがな1文字につき16進数6桁、SHIFT_JISでは16進数4桁で表される。)文字化けを防ぐため、コード内にエンコーディング文字指定を行うことを忘れないようにしなければならない。(基本はUTF-8が望ましい) ## 第5章 URIの設計 ### 5.1 クールなURLは変わらない リンクは一度URIの名前が変更されてしまうと動作しなくなる。(404:ページが見つかりませんの画面に飛ぶ。)こうしたリンク切れは、1990年代後半には当たり前のように起きており、Webの発明者Tim-Berners-Lee氏が「クールなURIは変わらない」と名言を残したほどである。 つまり、よく設計できたURIはリンク切れにならないのである。 ### 5.2 URIを変わりにくくするためには #### 5.2.1 言語に依存した拡張子やパスを含めない * 言語依存した拡張子がついたファイル名(例1)loginservlet.java * 言語依存したパス(例2)/login/LoginServlet こうしたURIは、一度言語を変更するとURIが無効となってしまう。 言語依存URIは、CGIの時代が終わり、言語が増えるにつれ見かけなくなっている。 #### 5.2.2 メソッド名やセッションIDを含めない * メソッド名が含まれている(例)login.do?action=showPage showPageはメソッド名である。これをshowpage1に変更すると無効となる。 * セッションIDが含まれている(例)?jsessionid = 50374869 セッションIDは毎回異なる値が発行されるため、セッションが終わると同時にURIも失効してしまう。 #### 5.2.3 URIはリソースを表現する名詞にする URIは全体として名詞として構築する必要がある。 (例)/sample/people/show/123 showという動詞が含まれている。**URIはHTTPメソッドという動詞に対する名詞である必要がある。** ### 5.3 URIの設計指針とユーザビリティ 以上のようなURIを変わりにくくするためのポイントを押さえた上で、**なるべくシンプルに**構成するのが良い。 良い例:http://example.jp/login #### シンプルな設計のメリット * 覚えやすい。 * 入力しやすい。 * 万人に分かりやすい。 ### 5.4 URIを変更したい時は 基本的には一度設計したシンプルなURIを変更してはならない。 構成上変更の必要が生じたときは、**新しいURIへリダイレクト**する形をとる。リダイレクトを用いることで、**旧来のURIを保持したまま新しいURIへの誘導が可能となる。** (例) 1. 変更前のURIにアクセス 2. 「ページが変更になりました。5秒後に自動的に新ページに飛びます」と表示される。リダイレクト失敗時(あるいは5秒待つ前に移動したい需要)に備え、変更後URIへのリンクも画面上に表示される。 3. 5秒後に変更後URIへのリダイレクトが行われる。 ### 5.5 URI設計のテクニック #### 5.5.1 拡張子で表現を指定する * **コンテントネゴシエーション**:HTTPが持つ**コンテント自動選択機能**のこと。クライアントが希望した表現を自動で設定する。リクエストヘッダにAccept(-○○)を追加する。 * メディアタイプ:Accept * 言語(日本語、英語etc…):Accept-Language * 文字エンコーディング:Accept-Charset * **言語を指定する拡張子**:コンテントネゴシエーションの場合、クライアント側の操作が必要である。しかし、**URIに言語を指定する拡張子**(.ja, .en等)を埋め込むことで、**容易に言語指定が可能となる。** また、.html, .json, .txt等でフォーマットを指定することもできる。 * 日本語版:http://example.jp/press.ja * 英語版:http://example.jp/press.en #### 5.5.2 マトリクスURI マトリクスURIは、階層構造を表す/の代わりに、**;または,で複数の軸のパラメータを区切る**方法である。**複数パラメータの組み合わせで表現するリソース**の場合に良く用いられる。 * 経度緯度:http://example.jp/map/35.705471,139.781898 ### 5.6 URIの不透明性 クライアントはURIを勝手に組み立ててはならない。 例えば、言語のURIの場合、フランス語版なら.frで終わると推測してアクセスしても、リソースがあるとは限らない。 クライアントはあくまでもサーバの提供するURIを扱うのであって、想像だけで勝手に構築したり構造変更してしまうと、とたんにシステムが動かなくなってしまう。 クライアントを作る際は、**URIが不透明であることを心掛けなければならない。** 勝手に推測されたり、クライアントから組み立てられるような仕組みにならないよう、**不透明さを維持した設計が肝要である。** ### 5.7 URIを強く意識する URIは次の点でとても重要である。 * **URIはリソースの名前である。** * **URIは寿命が長い。** * **URIはブラウザがアドレス欄に表示するものである。** これらの観点から、URIはWebサービスやWebAPIの設計において最も重視するべきパーツであるといえる。 ###### tags: `読書`