『Webを支える技術』読書記録　第１部〜第３部

#はじめに
今回『Webを支える技術』という本を読みましたので、自分なりにアウトプットしていく目的でまとめます。
リンク：[『Webを支える技術――HTTP、URI、HTML、そしてREST』](https://gihyo.jp/magazine/wdpress/plus/978-4-7741-4204-3)


# 第１部 Web概論

##第１章 Webとは何か

###Webの用途

具体的なWebの用途は３つに分けられる。

- Webサイト
　Google、Yahoo!等、最も身近であり、規模の大小など多くのバリエーションがある。Webサイトの裏がどのようになっているか、気にしないで済むことがWebの大きな特徴である。


- ユーザーインターフェース（UI）
　各種デバイスの設定画面や、HTMLによるヘルプの記述など。HTMLの記述、編集のしやすさ、ブラウザが多様な環境で使用できることにより、応用がなされている。

- API
　プログラム向けのインターフェース。データフォーマットはXMLやJSONなどプログラムで解釈、処理しやすいものを用いる。

以上、３つである。

###Webを支える技術　HTTP URI HTML

　Webを支える最も基本的な技術は、HTTP、URI、HTMLである。これらはシンプルな技術であり、それによってWebは様々な応用が可能になっている。また、これら３つに支えられたWebはハイパーメディアシステムと分散システムの２つの側面を持っている。

- ハイパーメディア
　テキストや映像など様々なメディアをハイパーリンクで結びつけて構成したシステム。非線形的にユーザがリンクを選択して情報を取得する。Webはハイパーメディアの一例であり、HTMLで記述したWebページには、他のWebページに埋め込まれた画像や映像のリンクが含まれ、ユーザはブラウザを使用し自由にそれらを辿ることができる。

- 分散システム（⇔集中システム）
　複数のコンピュータを組み合わせて処理を分散させる形式。一つのコンピューターでは、収まりきらない膨大な情報を効率的に処理できる。プロトコルがシンプルであることが特徴で、それにより、大規模なシステムを実現している。

以上、２つである。


##第２章 Webの歴史

###Web以前のインターネット

　初期のインターネットにはWebが存在しなかった。Web以前のハイパーメディアの例として３つ挙げられており、MemexとXanadu、HyperCardである。この中でHyperCardは初の実用的なハイパーメディアであると言われている。
　これらの問題点として挙げられているのは、リンク機能が複雑すぎることである。現在のWebは必要最低限のリンク機能だけを備えており、それが成功の一因と言える。

　また、Web以前の分散システムについても技術的な問題点が存在する。

　まず、分散システムを実現するための技術として、RPCという各サーバーの機能を他のサーバーやクライアントから呼び出す技術がある。これは単に、関数を呼び出すしくみである。
　この後に、オブジェクト自体をリモート側に配置する「分散オブジェクト」と呼ばれる技術が考案された。その代表例としてCORBA、DCOMなどが挙げられる。しかし、これらは非常に複雑な上、互換性も無いという問題があった。

　RPCに関しては現在でも、NFSなどの分散システム実装に使用されているが、性能劣化が激しいというの問題や、データ型変換の問題、インタフェースバージョンアップ時の互換性の問題、負荷分散が困難であるという問題などにより、動作する相手がある程度決まっているイントラネット環境に限定されてしまっている。

###Web普及の加速化

　Webというハイパーメディアの特徴はインターネットを使用していることである。インターネットはシステムを大規模化させやすい反面、情報の集中的管理が困難である。現在のWebが実現しているリンクは単方向のみのシンプルなものであり、これが普及の一助となっている。RPCとは違いWebは不特定多数のアクセスを、HTTPというシンプルなプロトコルによって可能にしている。

　爆発的に普及していったWebは、それを構成する要素であるHTTP、URI、HTMLの標準化が求められた。これらの標準化を行う団体としてW3Cが設立される。当時のHTML、CSSの標準化をめぐる状況は「ブラウザ戦争」と呼ばれる。各種サーバとブラウザの実装経験、HTTP、URIの仕様策定の過程で徐々に改善がなされていく。

###ハイパーメディアフォーマットとWebAPI

　初期のWebではHTMLが唯一のハイパーメディアフォーマットであった。その後、IETFによりAtomが標準化されるが、データの記述には冗長であるということで、JSONがデファクトスタンダードとなった。

　Webの用途の多様化によりWebAPIを巡っての議論が起こる。そこで、SOAPというプロトコルが登場するが、同じような仕様の乱立、仕様書自体の肥大化により批判が起こる。ここでRESTというアーキテクスチャスタイルが登場する。
　最終的に、SOAPより手軽に扱うことのできるRESTスタイルによってGoogleやAmazonはAPIを提供し、普及していった。そのRESTの普及と並行して、ユーザーインターフェースはWebで統一され始める。現在のソフトウェアの多くはWebが前提となっている。


##第３章 REST - Webのアーキテクスチャスタイル

###「REST」というアーキテクスチャスタイル

　WebのアーキテクスチャスタイルはRESTであり、これはクライアント/サーバから派生したものである。そもそも、実装から抽象度を一つ上げたものがアーキテクスチャでそこからもう一つ抽象度を上げたものがアーキテクスチャスタイルであり、WebにおいてRESTの約束を守ることが重要である。

　Web上の情報のことをリソースと言い、各々一意のURIを持っている。このURIが備える、リソースを簡単に指し示せる性質のことを「アドレス可能性」といい、これがプログラムの作成を容易にしている。また、サーバとクライアントの間でやり取りするデータのことを「リソースの表現」という。一つのリソースは複数の表現を持ち、状況によって変化する場合もある。

　RESTは以下の６つのアーキテクスチャスタイルを複合したものである。

- クライアント/サーバ
　これの利点はクライアントとサーバに分離して処理できることであり、PCだけでなく携帯電話などからもアクセスできるなど、マルチプラットフォームを実現している。また、ユーザーインターフェースはクライアントが担当するため、サーバはデータストレージ機能の提供のみとなる。

- ステートレスサーバ
　クライアントのアプリケーション状態をサーバで管理しないスタイル。Cookieはステートフルなセッション管理となっているため、必要最低限の利用が望ましい。

- キャッシュ
　リソースの鮮度に基づいて、一度取得したリソースをクライアント側で使いまわし、サーバとクライアントの通信を減らすことで処理時間を縮小し、効率的な処理を行うスタイル。しかしこれは、情報の信頼性に問題がある。

- 統一インターフェース
　URIで指し示したリソースに対する操作を統一した限定的なスタイル。インターフェースの柔軟性に制限を加えることで、全体のアーキテクチャがシンプルになり、クライアントとサーバの実装の独立性が向上する。統一インターフェースはRESTを最も特徴づけるスタイルである。

- 階層化システム
　HTTPにインターフェースを統一することにより、システムをいくつかの改装に分離するスタイル。

- コードオンデマンド
　プログラムコードをサーバからダウンロードし、クライアント側で実行するスタイル。これの利点は、クライアントがあとから拡張できるところにあるが、ネットワーク通信におけるプロトコルの可視性が低いという欠点もある。

　これら６つの、RESTに基づいたアーキテクチャスタイルの構築を念頭に置きながらも、状況に応じたスタイルを用い、実際に動作して価値の提供できるシステムを作ることが重要である。

　RESTに基づいたWebサービスでは、ハイパーメディアの基本機能であるリンクをたどる作業によって、アプリを実現する。これは「接続性」とも呼ばれる。また、統一インタフェースによって固定されているため、互換性の問題も発生しない。Webは、RESTという分散ネットワークシステムのための理論があったからこそ、成功したと言える。


#第２部 URI

##第４章 URIの仕様

###URIとは

　URIとは「リソースを統一的に識別するID」のことであり、インターネット上で必ず一意になるホスト名の仕組みと、ホスト内で必ず一意になる階層的なパスを組み合わせることで重複を防いでいる。また、URIには他にもポート番号や、クエリパラメータ、URIフラグメントなど様々な構成要素がある。

　URIには絶対URIと相対URI(/foo/bar)がある。カッコ内に記述したように、相対URIはURIスキーム(http等)やホスト名を省いてパスだけで表現する。
　相対URIの起点となるURIを指定するのがデータURIである。相対URIを絶対URIに変換する(相対URIを解決する)ためにはデータURIが必要となる。

###%エンコーディング

　URI仕様では、アルファベットや数字、記号などのASCII文字がパスに使用できると定められている。これら以外の文字をURIに入れるときは％エンコーディングという方式を用いる。

　WebサービスやWebAPIを実装する場合はなるべく、絶対URIを使用し、％エンコーディングとしてUTF-8を用いるのが望ましい。

##第５章 URIの設計

###「変わらないURI」

　URIの設計において「変わらないURI」を目指すことが重要である。そのために気をつけるべき事柄が５つある。

- プログラミング言語依存の拡張子(.pl .rb .do等)を利用しない。
- 実装依存のパス名(cgi-bin servlet等)を利用しない。
- プログラミング言語のメソッド名を利用しない。
- セッションIDを含めない。
- リソースを表現した名詞として記述する。

　以上を適用し、シンプルなURI設計をすることが望ましい。シンプルなURIはユーザビリティが高く、開発者ではないユーザでも使いやすい。

　また、URIを設計するときに使える技術として、拡張子で表現をしているする方法と、マトリクスURIがある。

　他に、サーバ側ではなく、クライアントアプリケーションを作る際のURIは不透明性が求められる。

　URIは、リソースの名前であり、寿命が長く、ブラウザのアドレス欄に表示されるなどの点でとても重要である。URIはWebサービスやWebAPIの設計において最も重視すべきパーツであると言える。

#第３部 HTTP

##第６章 HTTPの基本

###HTTPの階層

　HTTPはWebの基盤となるプロトコルであり、TCP/IPをベースにしている。インターネットのネットワークプロトコルは階層型になっており、４つの層に分けられている。以下に、層の下から列挙する。

- ネットワークインターフェース層
　物理的なケーブルやネットワークアダプタに相当する層。

- インターネット層
　ネットワークでデータを実際にやりとりする層で、IPが担当する。

- トランスポート層
　データの転送を保証する層で、TCPが担当する。転送するデータがどのアプリケーションに渡るかを決定するのがポート番号であり、HTTPでは、デフォルトで、80番ポート番号を使用している。

- アプリケーション層
　具体的なインターネットアプリケーションであり、HTTPを実現する層である。

###プロトコルの開発

　現在最も広く利用されているHTTPのバージョンは、1.1である。以前には0.9、1.0が存在した。Web発明当初のヘッダのないプロトコルが0.9で、IETFで最初に標準化が行われたバージョンが1.0である。

　RFC2616が現在の1.1の仕様であり、このHTTP1.1を有効活用するのが現在の開発スタイルで、完成度を上げていく活動のことを「HTTP Bis」という。

###リクエスト/サーバ

　HTTPではクライアントが出したリクエストをサーバで処理してレスポンスを返す。これをリクエスト/レスポンス型という。クライアントでは、以下６つの処理がなされる。

- リクエストメッセージの構築
- リクエストメッセージの送信
- レスポンス返信待機
- レスポンスメッセージの受信
- レスポンスメッセージの解析
- 目的達成に対する処理

  また、サーバー側では以下７つの処理がなされる。

- リクエスト待機
- リクエストメッセージの受信
- リクエストメッセージの解析
- アプリケーションへの処理の委譲
- アプリケーションからの結果を取得
- レスポンスメッセージの構築
- レスポンスメッセージの送信

　リクエストメッセージとレスポンスメッセージをまとめてHTTPメッセージという。リクエストメッセージはリクエストライン、ヘッダ、ボディ(無い場合もある)の３つ、レスポンスメッセージはステータスライン、ヘッダ、ボディの３つで構成される。

###ステートレスなプロトコル

　HTTPはステートレスなプロトコルとして構成されている。ステートフルでは、サーバがクライアントの状態(アプリケーション状態)を管理し続けるため、スケールアウトさせにくいという欠点がある。ステートレスではリクエストの処理に必要な情報が全て含まれた「自己記述的メッセージ」を使用するため、サーバ側のシステムが単純になる。

　しかし、ステートレスにも欠点があり、送信するデータ量が多い、サーバに負荷がかかる処理を繰り返すなど、パフォーマンスの低下や、通信エラーへの対処に問題がある。


##第７章 HTTPメソッド

###HTTPの８つのメソッド

　HTTPメソッドはGET、POST、PUT、DELETE、HEAD、OPTIONS、TRACE、CONNECTの８つある。TRACE、CONNECTは現在ほとんど使用されていない。これらのうち、GET、POST、PUT、DELETEは「CRUD」(Create,Read,Update,Delete)という性質を満たす、代表的なメソッドである。

- GET
　指定したURIの情報を取得する。

- POST
　あるリソースに対する子リソースの作成、既存リソースへのデータ追加、他のメソッドで対応できない(URIが長くなり過ぎる場合など)処理を行う。サーバ側がURIを自動で決定する際に用いる。

- PUT
　リソースの更新、リソースの作成。クライアントにURIの決定権がある場合に使用する。
- DELETE
　リソースの削除を行う。
- HEAD
　リソースのヘッダのみを取得する。
- OPTIONS
　リソースがサポートしているメソッドの一覧を返す。

　現実に一番多く利用されているのはGETとPOSTのみである。POSTに_methodパラメータを用いたり、X-HTTP-Method-Overrideヘッダを利用し、PUTとして扱うことができる。

　また、HTTPメソッドと更新日時などのヘッダ(If-Modified-Sinceなど)を組み合わせることで、「条件付きリクエスト」を送ることができる。

###「べき等性」と「安全性」

　HTTPメソッドの性質には「べき等性」と「安全性」というものがある。

- べき等性
　ある操作を何回行っても結果が同一であること。

- 安全性
　操作対象のリソースを変化させないこと。

　GETとHEADは、べき等かつ安全であり、PUTとDELETEは、べき等だが安全ではない。POSTはべき等でも安全でもないメソッドである。

　しかし、メソッドの誤用によって、べき等性や安全性が損なわれる。GETにおいてはリソースの更新や削除の実行、PUTではリソースの相対的差分の送信を行うべきではない。
　また、エイリアスリソースのような変化するリソース(バージョンなど)は更新や削除などができないよう設計する必要がある。

　このようにメソッドを限定して固定したことによりプロトコルがシンプルに保たれ、Webは成功したと言われている。


##第８章 ステータスコード

###ステータスコードの分類

　ステータスコードは３桁の数字であり、先頭の数字によって以下の５つに分類される。

- 1xx：処理中
- 2xx：成功
- 3xx：リダイレクト
- 4xx：クライアントエラー
- 5xx：サーバエラー

　ステータスコードを先頭の数字で分類するのは、クライアントとサーバを疎結合にするための工夫である。これにより、サーバのバージョンアップやクライアントの置き換えが行いやすく、また、ステータスコードの追加に対応しやすい。

　頻出のステータスコードは９つある。

- 200 OK
　　リクエストの成功を示す。

- 201 Created
　　リソースの作成成功を示す。
- 301 Moved Permanently
　　リクエストで指定したリソースが新しいURIに移動したことを示す。
- 303 See Other
　　リクエストに対する処理結果が別のURIで取得出来ることを示す。
- 400 Bad Request
　　リクエストの構文や、パラメータが間違っていたことを示す。
- 401 Unauthorized
　　適切な認証情報を与えずにリクエストを行ったことを示す。
- 404 Not Found
　　指定したリソースが見つからないことを示す。
- 500 Internal Server Error
　　サーバ側の異常により正しいレスポンスが返せないことを示す。
- 503 Service Unavailable
　　サーバがメンテナンスなどで一時的にアクセスできないことを示す。

　また、WebAPIの場合は、クライアントが解釈できる形式でエラーメッセージを返す必要がある。エラーが起きたときにどのステータスコードを返すかは設計において非常に重要である。


##第９章 HTTPヘッダ

###主なHTTPヘッダ

　HTTPヘッダはメッセージのボディに対する付加的な情報、メタデータを表現する。認証やキャッシュなどの機能はヘッダで表現する。以下で用途別に主なHTTPヘッダを挙げる。

- 日時を表す
　Dateヘッダ、Expiresヘッダなど。

- MIMEメディアタイプ
　メッセージでやりとりするリソースの表現の種類を指定する。ボディの内容を示すContent-Typeヘッダ(タイプ名/サブタイプ名)がある。
　MIMEメディアタイプはcharsetパラメータを所持することができるが、省略も可能である。しかし、タイプがtextの場合は必ずcharsetパラメータをつける必要がある。
例：text/plain, image/jpeg, audio/mpeg, video/mp4 etc…

- 言語タグ
　Content-Languageヘッダ：リソース表現の自然言語を指定するヘッダである。
- コンテントネゴシエーション
　Acceptヘッダ：クライアントがメディアタイプをサーバに伝える場合に使用する。
　Accept-Charsetヘッダ：クライアントが文字エンコーディングをサーバに伝える場合に使用する。
　Accept-Languageヘッダ：クライアントが言語タグをサーバに伝える場合に使用する。
- 長さの指定
　Content-Lengthヘッダ：ボディの長さを10進数のバイトで示す。
- チャンク転送
　Transfer-Encodingヘッダ：ファイルサイズが決まっていない場合に使用する。

###HTTP認証

　現在主流のHTTP認証には２種類ある。

- Basic認証
　ユーザ名とパスワードによる認証。求められるセキュリティ強度によって、SSL、TLSを使用しHTTPS通信を行い暗号化するか検討する必要がある。

- Digest認証
　Basic認証よりセキュアな認証。パスワードを盗まれる危険性は無いが、メッセージを暗号化したい場合はHTTPSの利用が必要である。

　WebAPIでは、WSSEというHTTP認証には認証の拡張仕様を使用する場合もある。

###キャッシュ

　HTTPの重要な機能にキャッシュがある。キャッシュとは、サーバから取得したリソースをローカルストレージに蓄積し、再利用する手法である。キャッシュ用のヘッダは３種類ある。

- Pragmaヘッダ
　　no-cacheのみ指定され、キャッシュ不可を示す。

- Expireヘッダ
　　キャッシュの有効期限を示す。
- Cathe-Controlヘッダ
　　上記どちらの内容も示すことができる。

　これら３つの使い分けとしては以下である。

- キャッシュ不可の場合は、Pragma、Cathe-Controlのno-cacheを同時に指定する。
- 有効期限が明確に決定している時は、Expireを使用する。
- 有効期限を相対的に指定したい場合はCathe-Controlのmax-ageを使用する。

　キャッシュを再利用する際は、条件付きGETを用いる。以下はその例である。

- If-Modified-Sinceヘッダ
 　リソースの更新日時を条件にする。更新日時はLast-Modifiedヘッダで確認する。

- If-None-Matchヘッダ
　リソースのETagを条件にする。ETagはリソースの更新状態の比較を行う文字列。

###持続的接続

　持続的接続とはリクエストの度に接続するのではなく、まとめて接続し続ける手法である。HTTP1.1の大きな新機能であり、この持続的接続が現在デフォルトとなっている。コネクションを切断したい場合は、リクエストでConnectionヘッダに、closeという値を指定する必要がある。

###標準外のHTTPヘッダ

　頻出するHTTPの標準外のHTTPヘッダの例が以下である。

- Content-Dispositionヘッダ
　サーバがクライアントに対してリソースのファイル名を提示する際に利用する。

- Slugヘッダ
　AtomのエントリをPOSTする際に、生成するリソースのURIのヒントとなる文字列をサーバに提示する。


##参考書籍詳細
WEB＋DB PRESS plusシリーズ『Webを支える技術――HTTP、URI、HTML、そしてREST』
山本陽平著　技術評論社　2010年5月1日　p.2~151