HTTP Variants
IETFのHTTP WGやQUIC WGのチェアをしているmnot氏より、キャッシュの効率が改善する「Variants」というHTTPレスポンスヘッダを定義する「HTTP Variants」という提案仕様が出ています。
この機能は、Fastly VCLの機能の標準化のようです。
少々想定している背景がわかりづらいのですが、自分なりに簡単にまとめてみる。
背景
Webにおいて、サーバはクライアントからのリクエストヘッダを見てコンテンツを出し分けています。
例えば、Accept-Languageリクエストヘッダを見てコンテンツの言語を変更しています。キャッシュサーバももちろんこのAccept-Languageを見て、それぞれ毎にコンテンツをキャッシュする必要があります。
次の例を見てみましょう
- 1. ブラウザは下記のHTTPリクエストを送信する
GET /foo HTTP/1.1 Host: www.example.com Accept-Language: en;q=1.0, fr;q=0.5
Accept-Languageヘッダで、英語もしくはフランス語のコンテンツを要求する
- 2. リクエストを受け付けたオリジンサーバは、下記のHTTPレスポンスを送信する
HTTP/1.1 200 OK Content-Type: text/html Content-Language: fr Vary: Accept-Language Transfer-Encoding: chunked [French content]
このオリジンサーバは英語のコンテンツは持っておらず、フランス語のコンテンツを返しています。Content-Languageヘッダでその旨が明示されています。また、Varyヘッダで、キャッシュサーバはAccept-Language毎にコンテンツをキャッシュすべきことを示しています。
問題点
この時の問題は、キャッシュサーバはオリジンサーバが結局どの言語のコンテンツを持っているか知ることが出来ない点です。
日本語もしくはフランス語を要求するユーザがいたらどうでしょうか?
Accept-Language: jp;q=1.0, fr;q=0.5
オリジンサーバが日本語に対応しているかはキャッシュサーバはわかりません。そのため、オリジンサーバはフランス語のコンテンツしか持ってなくても、キャッシュサーバはそのことを知らないので、そのままリクエストをオリジンサーバに転送します。
キャッシュサーバはそのリクエストをオリジンサーバに送った後に、「Content-Language: fr」のHTTPレスポンスヘッダを受け取り、日本語には対応してないことを知ります。キャッシュしてあるフランス語のコンテンツを使えたはずなのに、オリジンサーバに問い合わせしてしまってます。
上記の例は、言語でしたが、Accept-Encodingヘッダでも同様です。
このような手間が発生しないように、オリジンサーバが対応している言語(コンテンツ)をキャッシュサーバに伝達出来るようにするのが「HTTP Variants」の仕組みです。
HTTP Variantsヘッダ
Variantsヘッダは、オリジンサーバがキャッシュサーバに自身がどのようなコンテンツを提供できるか明示できます。
HTTPレスポンスのヘッダに下記のように追加します。
Variants: Content-Language;fr;de
このオリジンサーバは、フランス語とドイツ語が提供できるということを意味しています。このVariantsヘッダが付いたHTTPレスポンスをキャッシュサーバが受けとることで、オリジンサーバが対応しているコンテンツを知ることが出来ます。
つまり、先の例で言えば日本語のコンテンツは提供していないので、日本語のコンテンツが要求されてもキャッシュしてあるフランス語のコンテンツを使えるということです。
以下のように、複数のVariantsを羅列することも出来ます。
HTTP/1.1 200 OK Content-Type: image/gif Content-Language: en Content-Encoding: br Variants: Content-Language;en;jp;de Variants: Content-Encoding;br;gzip Vary: Accept-Language, Accept-Encoding Transfer-Encoding: chunked
このVariantsで指定されたヘッダのセマンティクスを理解しているサーバは、Varyヘッダを無視しなければなりません(MUST)。Variantsヘッダを用いることで、Varyヘッダで指定されたヘッダ毎にキャッシュする必要はなくなります。