読書:Real World HTTP 第2版


Real World HTTP 第2版を読んだので感想をまとめます。
著者:渋川よしき
出版社:オライリージャパン
発売日:2020/4/21

所感

ネットワーク周りの知識が欲しくて読みました。
同じカテゴリ?でマスタリングTCP/IPが有名ですが、当書は題の通りHTTPがメインなので視点が違って勉強になりました。

全て読んだので内容はかなりボリュームがありましたが、現在では使われていない技術の紹介もあるので飛ばしながら読んでも良かったな〜と思います。

サンプルコードにGoが使ってありますが、プログラミング経験があれば問題なく読めるかと思います。

学べたこととして、HTTP通信がどのように行われているのか(1つリクエストを送るのにも多くの技術の上に成り立っている)を詳しく理解することができました。
また、HTTPの進歩はセキュリティーの進歩でもあり、安全なサービスを作るための前提知識を得ることもできました。

ただ、かなり幅広い技術が載っているので浅い説明の部分も多々あります。
帯にある通り

これReal World HTTPでみたやつだ

の状態になる本で、実務で活かすためには残念ながら個々の技術を別途勉強する必要がありそう。

目次

1.HTTPの基本
2.HTTP/1.0のセマンティクス
3.Go言語でHTTPクライアントを実装
4.HTTP/1.1
5.HTTP/1.1のセマンティクス
6.HTTP/2,HTTP3
7.HTTP/2,HTTP3のセマンティクス
8.RESTful API
9.JSから動的なHTTPリクエスト
10.ウェブアプリケーションの基礎
11.ウェブの技術
12.ブラウザのセキュリティ

1-HTTP/1.0

HTTPはブラウザとWebサーバーが通信する際に用いられるプロトコル。
HTTPにももちろんバージョンがある。中でも、基本となる1.0(1996年公開)への理解は大事。
抑えるべき点は以下4つ
1. メソッドとパス
2. ヘッダー
3. ボディ
4. ステータス

いろいろなプロトコルを使えるcurlで手軽に試せる。
curlでHTTP/1.0を利用する例
ちなみに、curlではUser-AgentやAcceptはデフォルトで付く。

$ curl -v --http1.0 http://github.com/アカウント名
*   Trying 52.192.72.89...
* TCP_NODELAY set
* Connected to github.com (52.192.72.89) port 80 (#0)
> GET /アカウント名 HTTP/1.0
> Host: github.com
> User-Agent: curl/7.64.1
> Accept: */*
> 
< HTTP/1.1 301 Moved Permanently
< Content-Length: 0
< Location: https://github.com/アカウント名
< connection: close
< 
* Closing connection 0

1.メソッドとパス

ヘッダの一番最初に書かれているもの。
GET,HEAD,POSTをサポートする。
今や必須のPUTやDELETEはまだオプション的な立ち位置。

2.ヘッダー

実は電子メールを参考にして作られた。
リクエスト、レスポンスのほかにエンドツーエンドヘッダー(最終受け取り者に渡される)、ホップバイホップヘッダー(経路が変わったら削除される)がある。

3.ボディ

ヘッダの空行の後に挿入されている部分
一回のレスポンスで1ファイルしか返ってこない

4.ステータス

サーバーからの応答を完結に表したものです。
3桁の数字からなり、100の位ごとに意味があります。
例で出したリクエストでは301のステータスが帰っており、これはリダイレクトを表している。
リダイレクトのレスポンスではLocationヘッダでリダイレクト先を示す。
リダイレクトを受け取ったブラウザはLocationに再度リクエストをする
curl -L --http1.0 http://github.com/アカウント名

2-HTTP/1.0のセマンティクス

セマンティクスは「意味」や「内容」という意味。
HTTPはヘッダーがかなり重要。
ブラウザもヘッダーを利用して便利な機能を多く作っている。

フォームの送信

Content-Type: application/x-www-form-urlencoded
リクエストがフォームの送信を表すヘッダー。
メソッドがGETならクエリに含まれる
POSTならボディに含まれる。
中身はクエリパラメータと識別する必要があるからURLエンコードされた値が入る。

enctype="multipart/form-data"を指定することでファイルなど複数ファイルをフォームで送信できる。

他にもヘッダで管理できるものは多くある。

  • 表示言語
    • Accept-Language
  • キャラクターセット
    • Accept-Charset
    • 今ではContent-TypeにMIMEタイプとセットで入れることが多い
  • ファイルの圧縮
    • Accept-Encoding
    • Content-Encoding
  • クッキー
    • Set-Cookie

中でもクッキーはプライバシー保護などの観点などから理解を深める必要がある。
クッキーを管理する属性

  • Expires,MaxAge
    • クッキーの寿命を設定、どちらもなければセッションクッキーになる
  • Domain
    • クッキーを送信する対象のサーバー。省略時はクッキーを発行したサーバー
  • Path
    • クッキーを送信する対象のpath
  • Secure
    • HTTPS以外では送信しない。
  • HttpOnly
    • JSからクッキーを操作できなくする 最近のブラウザではクッキーは同一のオリジンでしか送信されない。 クッキーは便利な反面リクエストごとに送信しているので通信速度に影響を与える

3-Go言語でHTTPクライアントを実装

Goははじめて使ったのですが簡単に環境構築ができたのでサンプルコードを気軽に試せました。
当書では、サンプルコードを手元で動かすことでクライアントやサーバーから見た、HTTPの流れを理解することができます。
HTTP/1.1やHTTP/2や3のサンプルコードも出てきました。

4-HTTP/1.1

HTTP1.0の翌年に策定。
主に通信の高速化と安全性が強化された。

Keep-Aliveによる通信の高速化

TCP/IPの通信を効率化する仕組み。
従来では通信のたびにコネクションを切断していたところを、一定の時間コネクションを維持することによってRTTを減らしている。
切断はタイムアウトが基本でクライアントとサーバーが各々管理している。
HTTP/2以降では常に有効になっている。
*RTT:パケットが往復する時間

TLSによる暗号化通信

トランスポート・レイヤー・セキュリティの略。
TLSは通信の安全性をプラスした新しいプロトコルを作り出す仕組み。(HTTPに限らず)
例)HTTP => HTTPS、SMTP => SMTPSなど
似たものにSSLがあり混乱しました。実はTLSの方が後にできたプロトコルでSSLの次世代規格です。SSLがTLSを指していることもあるよう。

TLSには多くの技術が使われており、別途勉強が必要。
1.ハッシュ関数
入力データから規則性のない、固定長データを作り出す関数
2.共通鍵方式
通信する人同士が同じ鍵で暗号を解釈する
パフォーマンスが良い。
3.公開鍵方式
公開鍵と秘密鍵をつかう。
暗号化(公開鍵)と複合化(秘密鍵)の鍵が違う。
より複雑だが、パフォーマンスが悪い。
4.デジタル署名
公開鍵方式の逆
秘密鍵を配って公開鍵を隠す
5.鍵交換
クライアントとサーバー間で鍵を安全に交換するアルゴリズム
TLSでは通信ごとに共通鍵を作りそれを公開鍵方式で送り、受け取った共通鍵で通信するらしい。複雑な鍵交換アルゴリズムを使っている。

TLSの流れ

1.通信したいSSL証明書を取得
2.サーバーが信頼できるか認証局に確認(証明書に発行者のデジタル署名があるので最終的にルート認証局にたどり着く)
*ルート認証局の証明はあらかじめブラウザにインストールされている。
3.鍵交換
4.受け取った鍵で通信

5-HTTP/1.1のセマンティクス

ファイルのローカル保存

Content-Dispositionヘッダーの指定によってファイルがブラウザに表示されたりダウンロードされたり挙動が変わる。

リモートプロシージャコール(RPC)

別のコンピュータのプログラムを動かす手法
APIに似ている?と思ったらRPCもAPIの一種であった。
一般に認知されているAPIはREST形式のもの。
RESTがURL形式なAPIであるのに対し、RPCは関数を直接叩くAPI。
RPCはシンプルでわかりやすい反面、クライアントが関数を知っておく必要がある。

WebDAV

分散ファイルシステムのプロトコル
別のサーバーのファイルを管理する時に使う。
実はファインダーで利用することができる。

共通の認証プラットフォーム

ウェブサービスの普及とともに、一人当たりのアカウント保持数が増えている。
管理をより簡単にする仕組みが普及した。

1.OpenId
既に登録されているウェブサービスのユーザー情報で他のサービスにログイン
2.OAuth
既に登録されているウェブサービスのユーザー情報の利用権限を他のサービスに与える。
OpenIdとの違いは認証と認可
3.OpenId Connect
OAuth2.0をベースに認証を使えるように拡張したもの
4.JWT
JSONをベースにした認証トークン
base64エンコードした文字列3つをピリオドで連結したもの
それぞれヘッダー、ペイロード、署名を表す。
ヘッダーに記載された署名アルゴリズムに従って署名を検証。
検証ができると、ペイロードの内容を取得できる。

6-HTTP/2,HTTP3

さらなる高速化と双方向通信やP2P通信などの動画の特性に合わせた通信が可能になった。

1.ストリームによる通信の高速化
一本のTCP接続の内部に仮想のTCPソケットを作成することで通信の並列化を実現。

2.通信がテキストベースからフレームと呼ばれるバイナリ構造になった
通信の実態がフレームへ

3.サーバープッシュ
クライアントから要求される前にコンテンツを送信する仕組み。
linkタグのpreload属性で指定できる。
プッシュされたコンテンツはキャッシュに入る。
*DNSの名前解決だけを先に行うpreconnectもある。

4.ヘッダーの圧縮
一般にヘッダーは大量にある => 圧縮することでデータ量を削減
HPACKと呼ばれる方式を採用している。
HPACKは頻繁に使われるヘッダーを静的テーブルにインデックス、同じコネクション内で使われたヘッダーを動的テーブルにインデックスしている。

7-HTTP/2,HTTP3のセマンティクス

スマートフォンからのアクセスがPCを超えたことによりスマホ対応のユースケースが増加した。
デザインを画面幅に合わせて変化させるメディアクエリやよりwebページを高速に配信するampなどが出現。
他にもブラウザからスマホアプリに飛ぶDeepLinkなどいずれもモバイルアプリケーションを意識した仕組みが普及した。

8-RESTful API

おなじみのREST
↓に書いてあるメソッドとリソースをURI、リクエスト結果をステータスで表す特徴を持つ。

安全かつべき等

リソースを変化させないもの
GET、HEAD、OPTIONS

べき等

何度実行しても結果が変わらないもの
DELETE、PUT

何でも屋のPOST

9-JSから動的なHTTPリクエスト

JSからHTTPリクエストを送れるようになったためajaxが登場し、webの可能性がより広がった。

Fetch-API

XMLHttpRequestにできることは全てできる。
追加でキャッシュの管理やサービスワーカーに対応している。
サービスワーカー:
スクリプトをブラウザに読み込ませることで通知やオフラインキャッシュができる。

WebSocket

双方向通信を実現するためのAPI
通信の流れ
1.サーバーが特定のIP、ポートでリッスン
2.クライアントからコネクトメッセージ
3.サーバーが受け入れる(Accept)
4.ソケットクラスのインスタンスがサーバーに渡される
5.送受信ができる

10-ウェブアプリケーションの基礎

Webの動作パターンは
第1世代
サーバーサイドレンダリング
第2世代
Ajax
第3世代
シングルページアプリケーション
第3.5世代
シングルページアプリケーション+サーバーサイドレンダリング

と進化している。
この調子だと、第4世代もすぐに来る?

11-ウェブの技術

データセンター環境を持たなくともクラウドによって大規模サービスを作りやすくなった。kubernetesなどがホットな領域。

ロードバランサー

アクセスを負荷分散させる技術。
一つのサーバーでサービスを管理すると、処理能力が足りない。
=>ロードバランサーを前段に置き、配下のサーバーにアクセスを分散させる。
リージョンを分けてその中でさらにアベイラビリティゾーンを分けることでさらに障害に強くできる。
アベイラビリティゾーン:リージョン内で物理的(電源、ネットワークなど)に違う環境。

キャッシュの運用

DNSやCDNはキャッシュを使うことで通信の効率化を行っている。

メリット
高速配信
オリジンに負荷がかからなので負荷分散ができる

デメリット
キャッシュは変更が反映されないなど扱いが難しいところがある。
対応例:普段はキャッシュ1日で運用し、変更前などにキャッシュ5分など短くする

12-ブラウザのセキュリティ

  • XSS
    • 悪意のあるスクリプトを埋め込まれる攻撃。
  • CSRF
    • ユーバーに意図しないリクエストを送信させる攻撃。
  • MITM
    • プロキシなど中間者が通信を盗む攻撃。
  • CORS
    • オリジンが違うサーバーへのアクセスを制御する仕組み。

などが紹介されていた。
基本的にフレームワークに従えば大丈夫そうだが、適切に扱う知識が必要。
とりあえず適切なヘッダーをつけることから。