Webを支える技術　読了メモ

# 第1部　Web概論
## Webとは何か
様々なWebの用途
- Webサイト：Amazonのようなショッピングサイト，Googleのような検索サイト
- ユーザーインターフェース：ルーターやテレビなどの設定画面
- プログラム用API：データフォーマットにXMLやJSONを使用するプログラム用のインタフェース

Webを支える最も基本的な3つの技術
- HTTP：WebサーバとWebブラウザの間でWeb情報をやりとりするための通信プロトコル
- URI：Web上に存在する情報を特定するための技術
- HTML：情報を表現する文書フォーマット

## REST
Webのアーキテクチャスタイルとアーキテクチャと実装
- アーキテクチャスタイル：REST
- アーキテクチャ：ブラウザ，サーバ，プロキシ，HTTP，URI，HTML
- 実装：Apache, FireFox, Internet Explorer

リソース
- リソースとはWeb上の情報
- 世界中のリソースはそれぞれのURIで一意の名前を持つ
- URIを用いることでプログラムはリソースが表現する情報にアクセスできる

RESTは次の6つを組み合わせたアーキテクチャスタイル
- クライアント/サーバ：ユーザインタフェースと処理を分離する
- ステートレスサーバ：サーバ側でアプリケーション状態を持たない
- キャッシュ：クライアントとサーバの通信回数を減らす
- 統一インタフェース：インタフェースを固定する
- 階層化システム：システムを階層に分離する
- コードオンデマンド：プログラムをクライアントにダウンロードして実行する

# 第2部　URI
## URIの仕様
URIの構文
- 全体：`http://blog.example.jp/entries/1`
  - URIスキーム：`http`：URIが利用するプロトコルを表す
  - ホスト名：`blog.example.jp`：ドメイン名かIPアドレスで，インターネット上で必ず一意になる
  - パス：`/entries/1`：ホストの中のリソースを一意に指し示す

複雑なURI
- 全体：`http://yohei:pass@blog.example.jp:8000/search?q=test&debug=true#n10`
  - URIスキーム：`http`
  - ユーザ情報：`yohei:pass`：ユーザ名とパスワードから成`:`で区切る
  - ホスト名：`blog.example.jp`：ホスト名とポート番号をまとめてホスト情報と呼ぶ
  - ポート番号：`8000`：TCPのポート番号を表し，省略した場合はデフォルト値が使われる
  - パス：`/search`
  - クエリパラメータ：`q=test&debug=true`：?の後ろにはクエリが続く
  - URIフラグメント：`#n10`：URIが指し示すリソース内部の詳細情報を特定するときに利用

絶対URIと相対URI
- 相対URIはURIスキームやホスト名を省いてパスだけで表現する
- 相対URIはそのままではクライアントが解釈できないため，相対URIの起点としてベースURIを用いる必要がある

URIで使用できる文字
- アルファベット：A-Za-z
- 数字：0-9
- 記号：-.~:@!$&'()

%エンコーディング
- URIは基本的にASCII文字から成る
- %エンコーディングを使用すると日本語の`あ`は`%E3%81%82`と表現される

URIの実装で気を付けること
- WebサービスやWEBAPIを実装する場合はなるべく絶対URIを使う
- ASCII以外の文字を入れる場合はなるべくUTF-8を使う

## URIの設計
変わりにくいクールなURIの条件
- プログラミング言語に依存した拡張子やパスを含めない （`.pl`, `LoginServlet`など）
- メソッド名やセッションIDを含めない（`showPage`, `jsessionid=123456`）
- HTTPメソッドが動詞の役割を持つため，URIはリソースを表現する名詞にする（`show`）

URIを変更するとき
- 古いURIを新しいURIに転送するリダイレクトを使う
- リダイレクトが実装されていると以下のようなレスポンスが返る
  ```
  HTTP/1.1 301 Moved Permanently
  Location: http://example.jp/new
  ```
  
コンテントネゴシエーション
- クライアントの言語設定に従って自動的に適した表現を返すことができる機能のこと
- 日本語OSの利用者が英語版のリソースにアクセスできるようにするには以下のようなURIを用いる
  `http://example.jp/2010/05/01/press.jp`
  `http://example.jp/2010/05/01/press.en`

マトリクスURI
- 地図の緯度，経度などの複数のパラメータ軸を表現するときはセミコロンで区切る
  `http://example.jp/map/lat=35.705471;lng=139.751898`
- カンマでで区切ることも可能で順序が意味を持つ場合に使用する
  `http://example.jp/map/35.705471,139.751898`

URIの不透明性
- クライアント側はあくまでサーバが提供するURIをそのまま扱うだけであるべきで，URIの内部構造を想像して操作したりクライアント側でURIを構築したりするべきではない
- URIをクライアント側で組み立てたり、拡張子からリソースの内容を推測したりできないことを「URIはクライアントにとって不透明である」と言い，クライアントを作る際はURIが不透明であることを心がけなければいけない
# 第3部　HTTP
## HTTPの基本
インターネットのネットワークプロトコルは階層型になっている
- アプリケーション層：メールやDNS，HTTPを実現する層．
- トランスポート層：TCPで接続先の相手に対してコネクションを張りデータの到達を保証する．
- インターネット層：指定したIPアドレスを送り先として，パケット単位でデータをやり取りする．
- ネットワークインタフェース層：一番下に位置し，物理的なケーブルやネットワークアダプタに相当する

クライアントで行われること
1. リクエストメッセージの構築
2. リクエストメッセージの送信
3. レスポンスが返るまで待機
4. レスポンスメッセージの受信
5. レスポンスメッセージの解析
6. クライアントの目的を達成するために必要な処理

サーバで行われること
1. リクエストの待機
2. リクエストメッセージの受信
3. リクエストメッセージの解析
4. 適切なアプリケーションプログラムへの処理の委託
5. アプリケーションプログラムから結果を取得
6. レスポンスメッセージの構築
7. レスポンスメッセージの送信

リクエストメッセージ
- リクエストライン（1行目）：メソッド，リクエストURI，プロトコルバージョンで構成
- ヘッダー（2行目以降）：メタデータで複数のヘッダーを持てる
- ボディ（ヘッダーの後に配置）：リソースを作成したり更新するときリソースの表現そのものが入る

レスポンスメッセージ
- ステータスライン（1行目）：プロトコルバージョン，ステータスコード，テキストフレーズで構成
- ヘッダ（2行目以降）：リクエストメッセージと同様
- ボディ：JSON，HTMLなどが含まれる

ステートフル
- サーバがクライアントのアプリケーション状態（セッション状態）を覚える
- 欠点としてクライアントの数が増えた場合にスケールアウトさせにくくなる

ステートレス
- クライアントがリクエストメッセージに必要な情報をすべて含める
- 利点：サーバ側のシステムが単純になりスケールが簡単にる
- 欠点：送信するデータ量が多くなる，認証などサーバに負荷がかかる処理を繰り返す必要がある
- 通信エラーへの対応も必要になる

## HTTPメソッド
8つのメソッド
- GET：リソースの取得（Read）
- POST：子リソースの作成，リソースへのデータの追加，その他の処理（Create）
- PUT：リソースの更新，リソースの作成（Update）（Create）
- DELETE：リソースの削除（Delete）
- HEAD：リソースのヘッダの取得
- OPTIONS：リソースがエクスポートしているメソッドの取得
- TRACE：自分宛てにリクエストメッセージを返す(ループバック)試験
- CONNECT：プロキシ動作のトンネル接続への変更

GETメソッド
```:リクエスト
GET /list HTTP/1.1
Host: example.jp
```
```:レスポンス
HTTP/1.1 200 OK
Content-Type: application/json

[
 {"uri": "http://example.jp/list/item1"},
 {"uri": "http://example.jp/list/item2"},
 {"uri": "http://example.jp/list/item3"},
 {"uri": "http://example.jp/list/item4"}
]
```

POSTメソッド
- 子リソースの作成（ブログ記事の投稿などの操作に使われる）
- 以下の例では`/list`の下に新たに`/item5`という子リソースを生成
```:リクエスト
POST /list HTTP/1.1
Host: example.jp
Content-Type: text/plain; charset=utf-8

こんにちは！
```
```:レスポンス
HTTP/1.1 201 Created
Content-Type: text/plain; charset=utf-8
Location: http://example.jp/list/item5

こんにちは！
```
- リソースへのデータ追加
```:リクエスト
POST /log HTTP/1.1
Host: example.jp

2010-10-10T10:13:00Z, GET/log, 200
```
```:レスポンス
HTTP/1.1 200 OK
```
- 他のメソッドで対応できない処理（キーワードが長い場合など）
```:リクエスト
POST /log HTTP/1.1
Content-Type: application/x-www-form-urlencoded

q=very+long+keyword+foo+bar
```

PUTメソッド
- リソースの更新
```:リクエスト
PUT /log HTTP/1.1
Host: example.jp
Content-Type: text/plain; charset=utf-8

こんばんは！
```
```:レスポンス
HTTP/1.1 200 OK
Content-Type: text/plain; charset=utf-8

こんばんは！
```
- リソースの作成
```:リクエスト
PUT /newitem HTTP/1.1
Host: example.jp
Content-Type: text/plain; charset=utf-8

新しいリソース/newitemの内容
```
```:レスポンス
HTTP/1.1 201 Created
Content-Type: text/plain; charset=utf-8

新しいリソース/newitemの内容
```

POSTとPUTの使い分けについて
- POSTでリソースを作成するときは，クライアントはリソースのURIを指定できず，URIの決定権はサーバにある
- PUTでリソースを作成するときは，リソースのURIはクライアント側が決定する
- twitterのように投稿のURIがサーバ側で自動的に決まるようなものはPOSTを用いる
- 逆にWikiのようにクライアントが決めたタイトルがURIになるようなものはPUTを用いる
- 特別な理由がない限りはPOSTを使う方が良い

DELETEメソッド
```:リクエスト
DELETE /list/item2 HTTP/1.1
Host: example.jp
```
```:レスポンス
HTTP/1.1 200 OK
```

HEADメソッド
```:リクエスト
HEAD /list/item1 HTTP/1.1
Host: example.jp
```
```:レスポンス
HTTP1.1 200 OK
Content-Type: text/plain; charset=utf-8
```

OPTIONSメソッド
```:リクエスト
OPTIONS /list HTTP/1.1
Host: example.jp
```
```:レスポンス
HTTP/1.1 200 OK
Allow: GET, HEAD, POST
```

べき等性と安全性
- べき等：ある操作を何回行っても結果が同じこと
- 安全：操作対象のリソースの状態を変化させないこと
- GET, HEAD：べき等かつ安全
- PUT, DELETE：べき等だが安全でない
- POST：べき等でも安全でもない



## ステータスコード
ステータスコードの分類
- 1xx：処理中（処理が継続していることを示す．リクエストを継続するか，プロトコルをアップデートして送信する）
- 2xx：成功（リクエストが成功したことを示す）
  - 200 OK：リクエスト成功
  - 201 Created：リソースの作成成功
- 3xx：リダイレクト（クライアントはレスポンスメッセージのLocationヘッダを見て新しいリソースへ接続する）
  - 301 Moved Permanently：リソースの恒久的な移動
  - 303 See Other：別のURIの参照
- 4xx：クライアントエラー（原因はクライアント側のリクエストにある．エラーを解消しない限り同じリクエストを再送信することはできない）
  - 400 Bad Request：リクエストの構文やパラメータの間違い
  - 401 Unauthorized：アクセス権不正
  - 404 Not Found：リソースの不在
- 5xx：サーバエラー（原因はサーバ側にある．サーバ側の原因が解決すれば，同一のリクエストを再送信して正常な結果が得られる可能性がある．）
  - 500 Internal Server Error：サーバ内部エラー
  - 503 Service Unavailable：サービス停止（メンテナンス中など）
  
## HTTPヘッダ
様々なヘッダ
- 日時：`Date: Tue, 06 Jul 2010 03:21:05 GMT`
- Content-Type：メディアタイプを指定（text, imageなど）
  `Content-Type: application/xhtml+xml; charset=utf-8`
- Charsetパラメータ：文字エンコーディングを指定する
- 言語タグ
  `Content-Language: ja-JP`

コンテントネゴシエーション
- クライアントが自分の処理できるメディアタイプをサーバに伝える場合，Acceptヘッダを利用する
- Acceptヘッダ：処理できるメディアタイプを伝えるヘッダ
- Accept-Charset：処理できる文字エンコーディングを伝えるヘッダ
- Accept-Language：処理できる言語を伝えるヘッダ

Content-Lengthとチャンク転送
- Content-Length：ボディの長さを指定する
  `Content-Length: 5538`
- チャンク転送：ボディを分割して転送する
  `Transfer-Encoding: chunked`

認証
- Basic認証：ユーザ名とパスワードによる認証方式
  `Authorization: Basic xxxxxx`
- Digest認証：Basic認証よりもセキュアな認証方式でハッシュ値を使う
- WSSE認証：WebAPIの認証に使われる
- OpenID：シンプルなシングルサインオン（Googleアカウントを使用した方式）
- OAuth：Webサービス間での認可の委譲

キャッシュ
- キャッシュはサーバから取得したリソースをローカルストレージに蓄積して再利用する手法
- キャッシュ用ヘッダ
  - Pragma　キャッシュを抑制する(no-cache)
  - Expire　キャッシュの有効期限を示す
  - Cache-Control　詳細なキャッシュ方法の指定

その他のHTTPヘッダ
- Content-Disopsition：ファイル名を指定する
- Slug：ファイル名のヒントを指定する
# 第4部　ハイパーメディアフォーマット
HTMLとは何か
- タグで文書の構造を表現するコンピュータ言語
- 2種類のメディアタイプがある
  - text/html：SGMLベース
  - application/xhtml+xml：XMLベース
- 拡張子には.htmlを用いる

XMLの基礎知識
- XML文書は木構造として表現できる
- XMLは要素で文書の構造を表現する
  - 要素は開始タグ，内容，終了タグから成る
  - 空要素：内容を持たない要素 `<br></br>`
- 属性：開始タグの中に `属性名="属性値"` という形式で複数記述可能
- XMLを記述するための特別な文字`<`等は`&lt;`のように表現する
- コメント：`<!-- コメント内容 -->`
- XML宣言：XML文書の先頭にはバージョンや文字エンコーディング方式を指定する
- 名前空間：複数のXMLフォーマットを組み合わせるときに，名前衝突を防ぐ目的で使う

HTMLの構成要素
- ヘッダ
- ボディ
  - ブロックレベル要素：文書の段落や見出しなど表現
  - インライン要素：強調や改行，画像埋め込みなどを表現
- id属性：文書内で一意なID．URIフラグメント(#)で利用やCSSでスタイルを指定するときに使用
- class属性：その要素が属するクラス．CSSでのスタイル指定やmicroformatsなどでメタデータを表現するときに利用する

リンク
- `<a>`要素：Webページへのリンクを設定する `<a href="http://sample.jp">リンク</a>`
- `<link>`要素：HTMLのヘッダでWebページ同士の関係を指定するために使う
- オブジェクトの埋め込み：動画などのオブジェクトを埋め込む
- フォーム：ユーザからの入力によってURIを生成するときに利用する．GETメソッドやPOSTメソッドを呼び出す．
- rel属性：リンク元とリンク先のリソースの関係を記述する．stylesheetなど

microformatsとは
- リンクの細かい意味やイベント情報などを表現するための技術
- elemental microformats：リンク関係(rel属性)を使ってメタデータを表現するフォーマット
- compound microformats：class属性を使って階層構造のあるメタデータを表現するフォーマット

Atomとは
- 幅広い分野での応用が可能な汎用XML
- ブログ，検索エンジン，写真管理など様々なWebサービスのWebAPIとして利用できる
- メンバリソース：Atomにおける最小のリソース単位
- コレクションリソース：複数のメンバリソースを含むリソース
- メディアタイプは`application/atom+xml`
- 拡張子は`.atom`
- 名前空間はhttp://www.w3.org/2005/Atom


Atom Publishing Protocol
- Atomを利用したリソース編集プロトコルの規定

JSONとは
- JavaScriptの記法でデータを記述できる
- 冗長性が低いという利点から主にデータ表現のフォーマットとして利用される
- メディアタイプはapplication/json
- 拡張子は.json
- JSONに組み込みで用意されているデータ型
  - オブジェクト
  - 配列
  - 文字列
  - 数値
  - ブーリアン
  - null
- 日時：組み込みとして日時型がないため，ISO 8601フォーマとの文字列として扱う
	
# 第5部　Webサービスの設計
リソース設計の指針
- Webサービスで提供するデータを特定する
- データをリソースに分ける
- リソースにURIで名前を付ける
- クライアントに提供するリソースの表現を設計する
- リンクとフォームを利用してリソース同士を結び付ける
- イベントの標準的なコースを検討する
- エラーについて検討する

バッチ処理
- 大量のリソースを作成したり更新する場合，リクエストを1回1回送信するとサーバへの接続回数が多くなりパフォーマンスが問題になる
- このようなとき作成・更新したいリソースを一括で送信（バッチ処理）できるようにWebサービスを実装する

トランザクション
- 複数のリソースにまたがった変更をひとまとまりに扱う
- バッチ処理のトランザクション化（複数の処理をPOSTで一括して送信する）
- 上位リソースに対する操作（上位リソースを操作して下位リソースを一括操作する）

排他制御
- 複数のクライアントが同時に1つのリソースを編集して競合が起きないように，1つのクライアントのみが編集するように制御する処理
- 悲観的ロック：あるユーザがリソースを編集している間，リソースをロックして他のユーザは編集できなくしてしまう
- 楽観的ロック：通常の編集では文書をロックせずに競合が発生したときだけ対処する
  - 競合を起こしたユーザに確認した上で更新または削除する
  - 競合を起こしたデータを、競合リソースとして別リソースに保存する（PUTの場合のみ）
  - 競合を起こしたユーザに変更点を伝えマージを促す（PUTの場合のみ）

リソースの設計
- 関係モデルからの導出
  - 関係モデルのER図からリソースを導出する）
  - 中心となるテーブルの1行を1リソースとする
  - データの持つ階層構造を考えることと，トップレベルリソースの存在を忘れないことが重要
- オブジェクト指向モデルからの導出
  - リソース間のリンク関係にはオブジェクト指向モデルのクラス間の関係が使える）
  - クラスの持つメソッドを操作結果リソースへと変換する
  - クラスの持つ豊富なメソッドをHTTPの限定されたメソッドに置き換えられる
  - 成果物としてクラス図やシーケンス図がある
- 情報アーキテクチャからの導出
  - 複雑なデザインを受け手にとって情報を探しやすくしたり，わかりやすくするための技術
  - 設計された情報アーキテクチャを持つWebサイトの構造は，ほぼそのままWebサービスに適用できる