将軍の備忘録

アウトプット用です。あしからず。

Real World HTTPを読んだ (2章のみ)

前回 (Real World HTTPを読んだ (1章のみ) - 将軍の備忘録) に引き続き、 個人的に気になったところを書いていきます。

Real World HTTP ―歴史とコードに学ぶインターネットとウェブ技術

Real World HTTP ―歴史とコードに学ぶインターネットとウェブ技術

コンテントネゴシエーション

  • サーバとクライアントは、別々に開発されているため、期待している形式が一致するとは限らない
  • 1リクエストの中でサーバとクライアントがお互いのベストな設定を共有する仕組み
  • ネゴシエーションにはヘッダを使う

以下、表を引用

リクエストヘッダー レスポンス ネゴシエーション対象
Accept Content-Type MIMEタイプ
Accept-Language Content-Language/htmlタグ 表示言語
Accept-Charset Content-Type 文字のキャラクタセット
Accept-Encoding Content-Encoding ボディの圧縮

こちらのブログでキャラセットについても改めて確認。

ファイルの種類の決定

以下のようなリクエストヘッダ(Accept)だった場合

image/webp
*/*;q=0.8
  • qは、品質係数と言われ、0から1まで指定する。デフォは1。
  • Webサーバは、WebPに対応していれば、WebPを返す
  • Webサーバが、WebPに対応していなければ、他のフォーマット(優先度0.8)をサーバーに要求

表示言語の決定

以下のようなリクエストヘッダの場合

Accept=Language: en-US,en;q=0.8,ja:q=0.6
  • en-US,en,jaの優先順位でリクエスト送る。
  • あまり使われておらず、<html lang="ja"> のようにHTMLタグの中で返しているページが多い

キャラクターセットの決定

以下のようなリクエストヘッダを送信するが、

Accept-Charset: UTF-8,Shift_JIS;q=0.7,*;=0.3
  • どのモダンブラウザも Accept-Charset を送信していない。
  • 理由はおそらくどのブラウザも全てのキャラクターセットを内包しており、ネゴシエーションする必要がないからと想像される
  • キャラクターセットは、MIMEタイプと一緒に Content-Type ヘッダーに格納される

圧縮による通信速度の向上

  • 圧縮アルゴリズムを使うとファイルをサイズを1/10程度にできる、結果処理時間が短くなる
  • コンテンツ圧縮を行うネゴシエーションはヘッダーの中だけ完了
  • 例)deflate,gzipを指定
Accept-Encoding: deflate, gzip
  • curlコマンドは、--compressedオプション
  • Googlegzipより効率が良い圧縮フォーマット Brotli の実装を公開
  • br を指定してリクエストを送り、サーバが対応していれば Brotli による高速化が行われる
  • クライアント、もしくはサーバが Brotil に対応していなければ、別のエンコーディング(たぶんgzip)のフォールバックされる

クッキー

  • クッキーは、ウェブサイトの情報をブラウザ側に保存する仕組み。
  • サーバ → クライアントに「これを保存しといて」という指示を出す
  • 例)最終アクセス日時と時間
Set-Cookie: LAST_ACCESS_DATE=Jul/31/2016
Set-Cookie: LAST_ACCESS_TIME=12:04
  • クライアントはこれをローカルのストレージに保存しておき、次回同じURLアクセスする時にリクエストヘッダーに加えて送る
  • HTTPはステートレスだがクッキーを使うことであたかもサーバーが状態を保持したステートレスであるかのように見せる
  • クッキーの用途
  • 無くなっても問題のない情報
  • サーバ側の情報から復元できる情報
  • 容量は4キロバイト
  • secure を付与すればHTTPS通信のみ、HTTPの場合は平文で送受信する。パスワードとか要注意
  • クッキーには属性がいくつか定義されている
  • Expires, Max-Age 、Domain属性、Path属性、Secure 属性、HttpOnly 属性、SameSite 属性

認証とセッション

プロキシ

  • HTTPなどの通信を中継したり、さまざまな付加機能(圧縮したり、キャッシュしたり) をよろしくやってくれる仕組み
  • プロキシとゲートウェイの違い
  • プロキシ:通信の内容を理解する。必要におうじてコンテンツを改変したり、サーバに変わって応答する
  • ゲートウェイ:通信内容をそのまま転送する。内容の改変もやらない

キャッシュ

  • 例えばすでにアクセスしてダウンロード済みのコンテンツの内容に変化がなければ、サーバからのダウンロードを制御し、それによってパフォーマンスをあげる仕組み。

    更新日時のよるキャッシュ

  • 例えば以下のようなレスポンスを含めたとする
Last-Modified:  Wed, 08 Jun 2016 15:23:45 GMT
  • ウェブブラウザがキャッシュ済みURLを再度読み込む際、日時をそのままヘッダーに入れてリクエストする
If-Modified-Since: Web, 08 Jun 2016 15:23:45 GMT
  • 次にWebサーバは、受け取った日時とサーバ上のコンテンツ日時を比較し、変更があれば通常通りレスポンスを返し、変更がなければ 304 Not Modified(ボディはない)を返す。

Expires

  • 更新日時を使ったキャッシュの場合、キャッシュの有効性を確認するための通信が発生してしまう
  • その通信自体をなくしてしまおうというのが、Expires
Expires: Fri, 05 Aug 2016 00:11:22 GMT
  • クライアントは、この期限内であれば新鮮と判断し、強制的にキャッシュを利用
  • 期限がすぎていれば新鮮ではないと判断
  • 期限内で一切問い合わせされなくなるので、要注意

Pragma: no-cache

  • クライアントからプロキシサーバに指示を送ることもある
  • 唯一仕様に定義されているのが, no-cache
  • 「リクエストしたコンテンツがキャッシュされていたとしても、オリジンサーバまでリクエストを届けてほしい」という指示

Etag

  • 上述のシーケンシャルな更新日時とは違って、ファイルに関連するハッシュ値を使って比較する
  • サーバは、レスポンスに Etag ヘッダをつける
  • 2度目以降のダウンロード時にクライアントは IF-None-Match ヘッダに Etag の値をつける
  • サーバは受け取ったEtagとリクエストされたfairunoEtagを比較する。
  • Apache2.3.15、Nginx、h2oが付与するEtagの書式は、更新日時 + ファイルサイズ となっている。

Cache-Control

  • 柔軟なキャッシュ制御が可能
  • Expiresよりも優先される
  • こちらのqiitaの記事がわかりやすかった

Vary

  • 同じURLでもクライアントによって返す結果が異なることを示すヘッダ
  • 例えば、ブラウザがスマホ用なのかPC用なのかとか
  • この表示が変わる理由にあたるヘッダを列挙することで、それぞれにあったキャッシュを返すことができる
  • 例)User-Agent, Accept-Languageの設定ごとにキャッシュする
Vary: User-Agent, Accept-Language

リファラ

  • ユーザがどの経路からウェブサイトに到達したかをクライアントがサーバに送るヘッダ。

検索エンジン向けのコンテンツのアクセス制御

robots.txt

User-agent: *
Disallow: /cgi-bin/
Disallow: /tmp
  • HTMLのメタタグにも記述できる
<meta name="robots" content="noindex" />

サイトマップ

Sitemap: http://www/example.org/sitemap.xml

おしまい。