「Webを支える技術」の書評と読書メモ
各所で紹介されている「Webを支える技術」をひよっこのWebプログラマーとして読んでみた。
前提として「WebはRESTfulであるべき」という一般論について、名の通りWebを支える技術として挙げられるURI,HTTP,ハイパーメディアフォーマットの3つの切り口から各章ごと展開されている。
最後に設計の部分に踏み込んで、RESTfulなWebサービスやWebAPIを作る流れの中で3つの技術の利用のされ方が具体的に記されていたので、経験が浅くてもイメージがしやすい作りになっている。
ただ、個人的に欲しかった情報である「Cookieを使ったセッション管理」については、今日のWebアプリケーションには不可欠な技術である一方RESTに反する(サーバーからのレスポンスが同じでもクライアントで保持しているCookieが異なると結果も異なってしまうから)ので深く言及はされていなかった。
以下読書メモ
第1部WEB概論
1~2章
WEBの様々な用途として、WEBサイトやUI(GUI)などがあるが、プログラム用APIとしての側面も
XMLやJSONといった型式が今でこそ主流だが紆余曲折を経ている
WEBを支えている本質的な技術はHTTP, URI, HTMLで、これらから成るWEBの側面は以下
- ハイパーメティアシステム:様々なメディアをハイパーリンクによって結びつける仕組み
- 分散システム:複数のPCを組み合わせて処理を分散させる仕組み
これらの技術は、WEB以前からあり、問題点は以下
ハイパーメティアシステム -> 全てがリンクによって相互に結びついているので単方向の現在と比べて複雑
分散システム -> RPCという閉じたネットワークだったので不特定多数のクライアント相手のシステムに不向き
2000年前後にWEB APIの仕様をRESTにするかSOAPやWS-*にするかという論争、 2004年ごろGoogleやAmazonによってシンプルなREST形式のWEB APIが提供され始めて論争は終結
RESTの普及と並行して、AjaxやCommetなどの技術的なブレイクスルーも
3章REST
RESTは複数のアーキテクチャスタイルから成る
- クライアント/サーバ :UIと処理を分離する
- ステートレスサーバー:サーバ側でアプリケーションの状態を持たない
- キャッシュ:クライアントとサーバの通信回数と量を減らす
- 統一インターフェース:インタフェースを固定する -> GETやPOSTなど8つ限定のメソッド
- 階層化システム:システムを階層に分離する -> すべてのサーバが同じインタフェースを採用する
- コードオンデマンド:プログラムをクライアントにダウンロードして実行
RESTとハイパーメディア
アプリケーション状態エンジンとしてのハイパーメディアを用いたアプリケーションはURI経由でリソースを他アプリケーションで再利用可能( = 接続性)
RESTと分散システム
- リンクをたどってアプリケーション状態を遷移する方がデータの粒度が大きいので性能が良い
- 統一インタフェースによってHTTPを実装したクライアントと同様に接続可能
WebサービスやWebAPIがRESTfulになるとWebは全体として良くなる
第2部URI
- リソースの名前
- 寿命が短い
- ブラウザがアドレス欄に表示
4章URIの仕様
UTF-8による%エンコーディングを採用するのがデファクトスタンダード
5章URIの設計
- プログラミング言語依存の拡張子やパスを利用しない <-メンテナンス性、可読性、言語間の互換性
- プログラミング言語のメソッド名やセッションIDを利用しない <-メンテナンス性、ログインのたびにセッションIDが変化
- リソースを表現する名詞にする <-リソースへの処理内容はHTTPメソッドで指定する
どうしてもURIを変更したい時はリダイレクトを使う
第3部HTTP
TCP/IPとは
- アプリケーション層:HTTP、SSH、DNS、SMTP
- トランスポート層:UDP、TCP <- データ転送の保証、HTTPは80番ポートがデフォ
- インターネット層:IP <- パケットを通信単位としてデータを送り出すことだけを保証
- ネットワークインタフェース層:Ethernet
☆クライアントがリクエストを送り、 サーバーがレスポンスを返す
HTTPメッセージ
リクエスト | レスポンス |
---|---|
リクエストライン | ステータスライン |
リクエストヘッダ | レスポンスヘッダ |
空行 | 空行 |
リクエストボディ | レスポンスボディ |
HTTPのステートレス性
クライアントが自らのアプリケーション状態を覚え、すべてのリクエストを自己記述的メッセージで送信する。
HTTPメソッド
メソッド | 意味 |
---|---|
GET | リソースの取得 |
POST | 子リソースの作成、リソースへのデータの追加、その他の処理 |
PUT | リソースの更新、リソースの作成 |
DELETE | リソースの削除 |
HEAD | リソースのヘッダ |
OPTIONS | リソースがサポートしているメソッドの取得 |
TRACE | プロキシ動作の確認 |
CONNECT | プロキシ動作のトンネル接続への変更 |
- リソースの作成をする上で、URIをサーバ側で自動的に決定する場合はPOST、クライアントが決めたものがそのままURIになるものはPUT
- _methodパラメータやX-HTTP-Method-Overriceヘッダを使うことでPOSTメソッドでPUTやDELETEの振る舞いをする
- If-Modified-Sinceヘッダ等の条件付きリクエストでメソッドの実行判断をサーバに委ねる
- If-None-Match <-リソースのEtagを条件にする
- べき等性と安全性を守って設計
ステータスコード
ステータスコード | 意味 |
---|---|
1xx:処理中 | 処理の継続。リクエストの継続かサーバーの指示に従ってプロトコルをアップデートして再送信 |
2xx:成功 | リクエスト成功 |
3xx:リダイレクト | クライアントはレスポンスのLocationヘッダを見て新しいリソースへ接続する |
4xx:クライアントエラー | クライアントのリクエストを原因としたエラーで再び同じリクエストを投げることができない |
5xx:サーバエラー | 同一リクエストの再送信で正常なレスポンスが得られるかも |
HTTPヘッダ
- 日時:Dates, Expires等
- メディアタイプとサブタイプ:Content-Typeのtext, application/xhtml+xml; charset=utf=8 <-文字エンコーディングの指定
- 言語タグ:Content-Language:ja-JP
- コンテントネゴシエーション:Accept: text/html, application/xhtml+xml,appli...<-処理可能メディアタイプを伝える その他にもAccept-Charset Accept-Languageなど
- チャンク転送;Content-Length: chunked <-ボディを分割して転送
- 認証:Authorization: Basic ハッシュ値(Basic認証) WWW-Authenticate: Digest realm="Example.jp", nonce = "ナンス" .... (Degest認証)<-サーバからnonceを得てハッシュ化したものをリクエストに詰めるのでBasic認証よりはセキュア
- 持続的接続;Connection: closeでパイプライン化
キャッシュ
☆取得リソースをローカルストレージに蓄積し再利用する手法やデータそのもの
キャッシュ用ヘッダ
- Pragma:キャッシュの抑制
- Exprires:キャッシュの有効期限を示す
- Cache-Control:詳細なキャッシュ方法の指定
第4部ハイパーメディアフォーマット
ハイパーメディアフォーマットとしてのHTML
<a>
(アンカー)要素のhref属性:他のWebページへのリンク
<link>
要素のrel, href属性:rel属性によるWebページ同士の関係を指定するリンク
<img>
要素のsrc属性:画像の埋め込み
<object>
要素のdata属性:画像以外のオブジェクトの埋め込み
<form>
要素のtarget, action属性:action属性がGETの場合、targetのURIとフォームへの入力結果によってリンク先のURIを生成する。action属性がPOSTの場合、リソースの作成など、入力をtargetのURIに送信するときに利用する
WebAPIのようにプログラムがクライアントのケースで、それぞれ意味を解釈してどのリンクをたどるべきかを機械的に判断する仕組みとしてmiicroformatsやAtomがある
例えば <a>
<link>
要素における rel="stylesheel"のリンク関係はもとのHTMLリソースを外部のCSSリソースにリンクするときに使う
その他にrel-license(ライセンス情報)やrel-nofollow(スパムリンク防止)、hCalendar(イベント情報)など
☆HTMLでリンクを設計する際は、「リンクでをたとることでアプリケーションの状態が遷移することを意識する
JSON
JavaScriptObjectNotation 多くの言語がライブラリを用意しているため、言語間のデータの受け渡しが可能 Webサービスにおいては、ブラウザがJavaScriptを実行できるので相性がよく、XMLよりデータ表現の冗長性が低いのでAjax通信で活躍する
JSONPによるクロスドメイン通信 -> 外部のサイトで提供しているHTML内のスクリプトから自分のAPIを呼び出すときなど
第5部Webサービスの設計
WebサービスやWebAPIのインタフェースをHTTPとURIを用いて設計・実装するが具体的にどういう視点を持ってリソースの設計をしていくかということ
リソース設計とは:クライアントとサーバの間のインターフェースの設計、つまりWebサービスやWebAPIの外部設計 -> どのようにリソースを分割し、URIで名前をつけて、相互にリンクを持たせるのかを考える作業
☆WebサービスとWebAPIのを分けて考えないことが重要 -> 両者は人間用のインターフェースとプログラム用のインターフェースの違いはあれど、HTTP、URI、ハイパーメディアフォーマットを使う意味では共通しているから結局Web上にあるリソース
リソース設計の指針
リソースの更新は基本的にPUT
-> ・バックアップデート:更新したいリソース全体をリクエストボディに入れる。実装が容易だがデータ量が大きい
-> ・パーシャルアップデート:一部分だけを送信する。Ajax等の非同期通信で、入力を都度サーバーに送る時など、帯域に優しい
リソースの削除
削除したいリソースのURIにDELETEを送る。親に従属する子リソースはまとめて削除するのが一般的。
バッチ処理
大量の処理を細々リクエストを送るのは性能によくないので一括で送信する
-> トランザクションを張ってエラーがあればなにも処理をしないか
成功と失敗部分を切り分けてクライアントに伝えるか
リソースの更新においては複数のクライアントを相手にするので排他制御をしてコンフリクトを防ぐ必要がある
リソース設計の手法
☆WebサービスとWebAPIを分けて考えない