Content-Encoding
使い方
Content-Encoding ヘッダーは、表現データに適用されたエンコーディングを、適用された順に列挙します。クライアントは元のコンテンツを復元するためにエンコーディングの連鎖を逆順にたどります。最も一般的な用途は圧縮で、サーバーとクライアント双方の CPU 時間と引き換えに転送サイズを削減します。
Accept-Encoding リクエストヘッダーは、クライアントがサポートするエンコーディングを通知します。サーバーはそのリストからエンコーディングを選び、選択結果を Content-Encoding レスポンスヘッダーで示します。受け入れ可能なエンコーディングがない場合、サーバーはレスポンスを非圧縮で送ります。
Content-Encoding が存在する場合、Content-Length のようなメタデータのヘッダーは、元のリソースではなくエンコード後の形式を指します。JPEG、PNG、ZIP のような事前に圧縮されたメディア形式はすでに内部に圧縮を含んでおり、追加のエンコードを施してもほとんど効果がありません。これらの形式にコンテンツエンコーディングを適用すると CPU を浪費し、転送サイズが増えることさえあります。
Content-Encoding ヘッダーは表現のエンコーディングを記述し、これはリソースのエンドツーエンドの性質です。これは、各ネットワーク中間装置で適用され取り除かれるホップバイホップの性質である Transfer-Encoding とは異なります。
注意
gzip は依然として最も広く導入されているエンコーディングです。Brotli は静的なテキストコンテンツに対して最良の圧縮率を提供します。Zstandard は高速な圧縮と高い圧縮率のバランスを備え、幅広いブラウザでサポートされています。
注意
リソースの元のメディアタイプは Content-Type ヘッダーが記述します。Content-Encoding は、基になるコンテンツの形式ではなく、現在の表現の圧縮状態を反映します。
gzip
32 ビット CRC を伴う Lempel-Ziv 符号化(LZ77)アルゴリズムです。1996 年に導入された gzip は、今も Web で最も広くサポートされているエンコーディングです。サーバーは x-gzip も別名として認識します。
compress
元は UNIX の compress プログラム由来の Lempel-Ziv-Welch(LZW)アルゴリズムです。特許上の懸念からこのアルゴリズムは衰退し、現代のブラウザで compress をサポートするものはありません。
deflate
deflate アルゴリズムを zlib の構造でラップしたものです。すべてのブラウザでサポートされていますが、gzip やより新しいアルゴリズムにおおむね取って代わられています。
br
Brotli アルゴリズムです。Brotli は、Web でよく使われる語の静的辞書を内蔵することで、特にテキストベースの Web コンテンツにおいて gzip より高い圧縮率を実現します。Brotli には HTTPS が必要です。主要なブラウザすべてでサポートされています。
zstd
Zstandard アルゴリズムです。Zstandard は gzip に匹敵する速度で圧縮しながら、Brotli に近い圧縮率を達成します。このアルゴリズムは 1(最速)から 22(最高圧縮率)まで設定可能な圧縮レベルをサポートし、サーバーは CPU 時間とペイロードの小ささを引き換えにできます。展開速度は、使用した圧縮レベルに関わらず一貫して高速です。
Zstandard は辞書ベースの圧縮もサポートしており、代表的なコンテンツで訓練した事前共有の辞書によってペイロードのサイズをさらに削減できます。Use-As-Dictionary ヘッダーと Compression Dictionary Transport の仕組みは、この機能の上に築かれています。
Chromium ベースのブラウザ、Firefox、最近の Safari でサポートされています。
dcb
辞書圧縮された Brotli です。Compression Dictionary Transport 仕様の一部として定義されています。クライアントとサーバーは Use-As-Dictionary ヘッダーと Available-Dictionary ヘッダーを通じて共有辞書をネゴシエートします。サーバーは共有辞書を使って Brotli でレスポンスを圧縮し、エンコーディングを dcb として示します。
dcz
辞書圧縮された Zstandard です。dcb と同じ辞書転送の仕組みを、Brotli ではなく Zstandard アルゴリズムで使います。サーバーはネゴシエートした辞書で圧縮し、エンコーディングを dcz として示します。
例
gzip で圧縮されたレスポンスです。これは Web で最も一般的なエンコーディングであり、すべてのブラウザでサポートされています。
Content-Encoding: gzip
Brotli で圧縮されたレスポンスです。Brotli は HTML、CSS、JavaScript のリソースについて、通常 gzip より小さなペイロードを生みます。
Content-Encoding: br
Zstandard で圧縮されたレスポンスです。Zstandard を選ぶサーバーは、Brotli に匹敵する圧縮率を高速な圧縮とともに得られます。
Content-Encoding: zstd
複数のエンコーディングが順に適用されています。リソースはまず deflate で、次に gzip でエンコードされました。クライアントは逆順にデコードします。まず gzip、次に deflate です。
Content-Encoding: deflate, gzip
辞書圧縮された Zstandard を使うレスポンスです。クライアントは以前に Use-As-Dictionary ヘッダーで辞書を受け取り、Available-Dictionary リクエストヘッダーでその辞書を通知していました。サーバーは共有辞書に対してレスポンスを圧縮しました。
Content-Encoding: dcz
トラブルシューティング
圧縮に関連する失敗は、ブラウザのデコードエラー、破損したダウンロード、非圧縮で届くレスポンスとして現れます。
二重圧縮が壊れたレスポンスを生む。リバースプロキシや CDN が、オリジンからのすでに圧縮済みのレスポンスを再圧縮し、クライアントがデコードできない不正なペイロードを生み出します。Content-Encoding ヘッダーに gzip, gzip のように値が積み重なっていないか確認してください。nginx では、オリジンがすでに圧縮している場合はプロキシでの圧縮を無効にします。
proxy_set_header Accept-Encoding "";
Cloudflare では、オリジンが事前圧縮済みのレスポンスを送る場合、Speed の設定で「Brotli」を無効にします。
ブラウザが ERR_CONTENT_DECODING_FAILED を表示する。このエラーは、Content-Encoding ヘッダーが宣言するエンコーディングが実際のボディの内容と一致しない場合に現れます。よくある原因は、オリジンが Content-Encoding: gzip を付けたまま非圧縮のボディを送っている、あるいはミドルウェアがエンコーディングを取り除いたのにヘッダーを残している、などです。curl -v -H “Accept-Encoding: gzip” https://example.re を実行し、生のボディが宣言されたエンコーディングと一致するか調べてください。gunzip にパイプして検証します。curl -s —compressed https://example.re | head のようにします。
圧縮後の Content-Length の不一致。Content-Length の値は、元のサイズではなく圧縮後のボディサイズを反映しなければなりません。不一致があると、ブラウザはレスポンスを切り詰めるか拒否します。nginx の gzip on を使う場合、nginx は Content-Length を自動的に再計算します。圧縮が実行される前に Content-Length を設定するミドルウェアがこの問題を引き起こします。Content-Length の設定を圧縮の後へ移すか、ヘッダーを削除してサーバーに chunked の Transfer-Encoding を使わせてください。
サーバーの設定があるのに圧縮が適用されない。サーバーは圧縮する前に Accept-Encoding リクエストヘッダーを確認します。Accept-Encoding が欠けているか空であれば圧縮は行われません。一部のプロキシは転送するリクエストから Accept-Encoding を取り除きます。nginx では gzip on が設定されていること、そして MIME タイプが一致することを確認してください。
gzip on;
gzip_types text/plain application/json
text/css application/javascript;
Apache では mod_deflate を有効にし、フィルターが適用されていることを確認します。
AddOutputFilterByType DEFLATE text/html
AddOutputFilterByType DEFLATE application/json
性能向上のために事前圧縮したファイルを配信する。リクエストのたびに圧縮するのは CPU の浪費です。代わりに、静的ファイルをあらかじめ圧縮してディスクから配信してください。nginx では gzip_static on を有効にすると、元のファイルと並んで .gz ファイルが配信されます。Apache では MultiViews を有効にするか、mod_rewrite を使ってリクエストを .gz や .br のバリアントへ対応付けます。デプロイの際に、事前圧縮したファイルが元のファイルと同期した状態を保つようにしてください。