Real World HTTP ― 歴史とコードに学ぶインターネットとウェブ技術」を読み終わった。

感想

  • 本のサブタイトルにある通り、HTTP や関連する仕様の策定の歴史と Go 言語によるミニマムな実装例をもとにインターネットとウェブの技術について学べる本。日本語で読める HTTP に関する書籍としては最も網羅的だと思うし、まえがきによると著者の方もそれを意図して書かれたようです。
  • 仕様の変更や新しい仕様が策定された経緯は最新の仕様を読むだけではなかなか知ることができないけど、本書はしっかりとサーベイした上で歴史的経緯が書かれていて、史料的な価値も高いと感じました。
    • 本書とは全く関係ない話ですが、史料的な価値を生み出すことを念頭に記事や本を書くのは歴史的経緯を知っている人の重要な任務じゃないかと思っていて、そういったことをしてくれる人が増えるといいな、と思っています (特に私が興味のあるウェブやシステムソフトウェア周辺で!)。私も Service Worker に関する記事を書いています。
  • この本の出版は 2017 年 6 月で最近なんですが、既にリアルワールドの状況は少しずつ変わり始めてて、その辺りに注目して読むのも面白いと思いました(内容的にはまったく問題ないレベルの変化です、念のため)。例えば、第 8 章で RSS サービスの例として名前が挙げられている LDR (Live Dwango Reader) はサービス終了のアナウンスがありましたし、Flash も廃止時期が具体的になりました。改訂版が出る際は、そういった差分情報が公開されるとウェブの発展が感じられて楽しそうです。

読書メモ

Twitter でのメモ書き

まえがき

本書は HTTP に関する内容を一冊に集めることを目的として企画されていて、「WebAPI: The Good Parts」と「ハイパフォーマンスブラウザネットワーキング」の間におさまる本として書かれている。まえがきを読むと、著者がどういう意図を持って本書を執筆したのか詳しく書かれているので一読すべき。

第 1 章 HTTP/1.0 のシンタックス:基本となる4つの要素

HTTP の歴史 (0.9 から 1.0)、HTTP の先祖 (電子メール、ニュースグループ) から受け継いだプロトコル、リダイレクト、URL など。

  • HTTP が電子メールとニュースグループのプロトコルを参考にしていること、RFC という名称の由来、リダイレクトの挙動辺りが勉強になった。
  • Mac のファイル種別の管理方法を知らなかった (リソースフォーク)。私は Windows 98 からインターネットを使い始めたんですが、Windows だと拡張子でファイルの種別が判断できるので、当時ウェブページを作るときに MIME タイプがなぜ必要なのか分かってなかったことを思い出しました。

第 2 章 HTTP/1.0 のセマンティクス:ブラウザの基本機能の裏側

フォームの送信(ファイル、リダイレクトなど)、コンテントネゴシエーション、クッキー、認証とセッション、プロキシ、キャッシュ、リファラ、検索エンジン向けのアクセス制御 (ronots.txt) など。

  • Apache が ETag の生成に inode を使っていた話が興味深い。実装時は複数台でロードバランスさせることを想定してなかったんだろうね。
  • Cache-Control ヘッダ周りの挙動がフローチャートで解説されてて分かりやすい。先日 CDN にプライベートデータがキャッシュされてしまった事故があったし、Cache-Control ヘッダ周りを触るときは読み返したい。個人的にはリクエストヘッダに指定した場合の挙動 (プロキシへの指示) が曖昧な理解だったので、整理できて良かった。
  • HTTP の “referer” のミススペルの話は Wikipedia の当該記事を見ると次のように書かれててとても切ない (HTTP referer - Wikipedia)。

document co-author Roy Fielding has remarked that neither “referrer” nor the misspelling “referer” were recognized by the standard Unix spell checker of the period.

第 3 章 Go 言語による HTTP/1.0 クライアントの実装

Go 言語を使った GET や POST リクエストなどの送受信方法の解説。あとはマルチパートフォームデータやクッキー、プロキシの使い方など。

第 4 章 HTTP/1.1 のシンタックス:高速化と安全性を求めた拡張

Keep-Alive、パイプライニング、TLS、PUT/DELETE メソッドと CRUD、プロトコルアップグレード、バーチャルホスト、チャンク方式など。

  • HTTP/1.0 までは 1 台のウェブサーバで一つのドメインのみを扱う前提だったためサーバが受け取る情報はパスだけだったが、HTTP/1.1 からは Host ヘッダーにリクエストを送りたいサーバ名を記述することが義務付けられて、バーチャルホストがサポートされるようになった。この話を聞くたびに「HTTP はパッチワークのように進化してきたんだな」と親近感が湧く。

第 5 章 HTTP/1.1 のセマンティクス:広がる HTTP の用途

ローカル保存、ダウンロードの中断再開、XHR、Comet、ジオロケーション、RPC、WebDAV、認証と認可の仕組みなど。

  • 「5.2 ダウンロードの中断、再開」を読むと、ダウンローダーがどういう仕組みで動いていたか分かる。ダイアルアップ接続の頃はダウンローダーに大変お世話になったものだけど、今じゃすっかり使わなくなったね。

第 6 章 Go 言語による HTTP1.1 クライアントの実装

Go による各機能の実現方法。TLS、証明書の作り方、プロトコルアップグレード、チャンク、RPC など。

  • 本章の冒頭に “コードを使って理解を補強するという目的もあります” とある通り、コードを流し読みすることで雰囲気を掴むことができました。

第 7 章 HTTP/2 のシンタックス:プロトコルの再定義

HTTP/2 プロトコルの概説、SPDY と QUIC、Fetch API、Server-Sent Events、WebSocket、WebRTC、HTTP Push など。

  • HTTP/2 といえばそれが盛り上がってる頃にちょうど JavaScript の Push API も実装中で、それが Promises を多用するものだから「Push の Promise が・・・」みたいな話でたびたび混乱していたことを思い出しました。
  • WebSocket のコネクション確立シーケンスを全然分かってなくて WebSocket 独自の仕組みがあると思い込んでいたのですが、実際は HTTP のプロトコルアップグレードの仕組みを使っていることを知りました。
  • Web Audio API の AudioWorker の話が一文出てくるけど、それは仕様から既に消えて AudioWorklet として再実装中です。Service Worker の説明が少なめなのと、CacheStorage API の話がなかったのが個人的に残念 (ポジショントークです!!1)

第 8 章 HTTP/2 のセマンティクス:新しいユースケース

レスポンシブデザイン、セマンティックウェブ、オープングラフプロトコル、AMP、HTTP ライブストリーミング、MPEG-DASH など。

  • 「セマンティックウェブは衰退した」みたいな話を何度か聞いたことがあるけど、その思想や成果は JSON-LD やオープングラフプロトコルといった規格の中で脈々と受け継がれているというのはちゃんと理解してなかった。今までセマンティックウェブと関連付けずにそれら規格を見てました。
  • 動画ストリーミング周りは今まで触れる機会がなかったので学びが多かったです。規格が策定されていった歴史的な経緯が興味深い。

第 9 章 Go 言語による HTTP/2、HTML 5 のプロトコルの実装

HTTP/2 サーバプッシュ、Server-Sent Events、WebSocket の Go 言語によるサンプル実装の紹介。

  • Go のサーバプッシュ API がプッシュ対象のリソースに対してサーバ側で疑似リクエストを発行するようになっているのは面白いなと思った。ウェブブラウザ内でも通常のナビゲーションとは違う場所からリソース読み込みを行うとき (例えば Service Worker の更新チェック時) に擬似的にリソースリクエストを発行してセキュリティチェックを通したりしているのでコードパスを再利用したいのかな。

第 10 章 セキュリティ:ブラウザを守る HTTP の機能

XSS、CSP、Mixed Content、CORS、MitM、セッションハイジャッキング、インジェクション、CSRF、クリックジャッキング、広告などなど。脅威の種類と対策を幅広く。

第 11 章 クライアント視点で見る RESTful API

RESTful と REST-ish、 RESTful API におけるメソッド・ステータスコード・ボディー、REST API の実例、タイムアウトやアクセス数制限など。

  • HTTP によるデータベースアクセスに関しては「4.3 PUT メソッドと DELETE メソッドの標準化」でも触れられている。
  • LSUDs (Large Set of Unknown Developers) の話を見て Web API の粒度を決めるのは本当に難しそうだと感じた。私は SSKDs (Small Set of Known Developers) しか設計したことがないのでモノリシックな API を作れば事足りたけど、ユースケースが事前に明確に決められない場合悩みすぎていつまでも API をローンチできなさそう。

補足

  1. 私は Chrome の Service Worker と Cache Storage API 実装者の一人です。