ASP.NET Core での応答の圧縮
ネットワーク帯域幅は限られたリソースです。 通常、応答のサイズを小さくすると、多くの場合、アプリの応答性が大幅に向上します。 ペイロード サイズを小さくする 1 つの方法は、アプリの応答を圧縮することです。
HTTPS を使用した圧縮
セキュリティで保護された接続での圧縮された応答は、EnableForHttps オプションで制御できますが、セキュリティ リスクがあるため、既定では無効になっています。 動的に生成されたページで圧縮を使用すると、CRIME と BREACH 攻撃にアプリが公開される可能性があります。 CRIME および BREACH 攻撃は、 ASP.NET Core で偽造防止トークンを使用して軽減できます。 詳細については、「ASP.NET Core でのクロスサイト リクエスト フォージェリ (XSRF/CSRF) 攻撃の防止」を参照してください。 BREACH 攻撃の軽減に関する情報については、http://www.breachattack.com/ で軽減策に関するページを参照してください
EnableForHttps
がアプリで無効になっている場合でも、IIS、IIS Express、Azure App Service は IIS Web サーバーで gzip を適用できます。 応答ヘッダーを確認するときは、サーバー の値を書き留めます。 予期しない content-encoding
応答ヘッダー値は、ASP.NET Core アプリの構成ではなく、Web サーバーの結果である可能性があります。
応答圧縮ミドルウェアを使用する状況
IIS、Apache、または Nginx でサーバーベースの応答圧縮テクノロジを使用します。 応答圧縮ミドルウェアのパフォーマンスは、おそらくサーバー モジュールのパフォーマンスに及ぶものではありません。 HTTP.sys サーバー と Kestrel サーバーでは、現在、組み込みの圧縮サポートは提供されていません。
アプリが次の場合は、応答圧縮ミドルウェアを使用します:
- 次のサーバーベースの圧縮テクノロジを使用できない。
- 次で直接ホスティングしている。
応答圧縮
通常、ネイティブに圧縮されていない応答は、応答の圧縮のベネフィットを受ける可能性があります。 ネイティブに圧縮されていない応答には、一般的に CSS、JavaScript、HTML、XML、JSON が含まれます。 PNG ファイルなどのネイティブに圧縮されているアセットは圧縮すべきではありません。 ネイティブに圧縮されている応答をさらに圧縮しようとすると、サイズや転送時間がわずかに減少しても、圧縮の処理にかかった時間のために意味がなくなってしまうことがあります。 約 150 から 1000 バイト未満 (ファイルの内容と圧縮の効率により異なる) のファイルは圧縮しないようにしてください。 小さいファイルを圧縮するオーバーヘッドにより、圧縮されていないファイルよりも大きい圧縮ファイルが生成される場合があります。
クライアントが圧縮されたコンテンツを処理できる場合、クライアントは Accept-Encoding
ヘッダーを要求と一緒に送信して、その機能をサーバーに通知する必要があります。 サーバーにより圧縮されたコンテンツが送信されるときには、圧縮された応答のエンコード方法に関する情報を Content-Encoding
ヘッダーに含める必要があります。 次の表に、応答圧縮ミドルウェアによりサポートされているコンテンツ エンコードの指定を示します。
Accept-Encoding ヘッダー値 |
ミドルウェアによるサポート | 説明 |
---|---|---|
br |
可 (既定) | Brotli 圧縮データ形式 |
deflate |
いいえ | DEFLATE 圧縮データ形式 |
exi |
いいえ | W3C 効率的な XML 交換形式 |
gzip |
はい | Gzip ファイル形式 |
identity |
はい | "エンコードなし" の識別子: 応答をエンコードできません。 |
pack200-gzip |
いいえ | Network Transfer Format for Java Archives |
* |
はい | 明示的に要求されていない、すべての使用可能なコンテンツ エンコード |
詳細については、「IANA Official Content Coding List」(IANA 公式コンテンツ コーディング リスト) をご覧ください。
応答圧縮ミドルウェアを使用すると、カスタム Accept-Encoding
ヘッダー値の他の圧縮プロバイダーを追加できます。 詳細については、下記の「カスタム プロバイダー」をご覧ください。
応答圧縮ミドルウェアは、クライアントからの送信時に、品質値 (qvalue q
) の重み付けに反応して圧縮スキームの優先度付けを行うことができます。 詳細については『RFC 9110: Accept-Encoding』をご覧ください。
圧縮アルゴリズムは、圧縮速度と圧縮の有効性のトレードオフの対象になります。 ここでの 有効性 は、圧縮後の出力のサイズを指します。 最小サイズは、最適な圧縮によって実現します。
圧縮されたコンテンツの要求、送信、キャッシュ、受信に関連するヘッダーを次の表に示します。
ヘッダー | Role |
---|---|
Accept-Encoding |
クライアントが受け入れ可能なコンテンツ エンコード方式を示すために、クライアントからサーバーに送信されます。 |
Content-Encoding |
ペイロード内のコンテンツのエンコードを示すために、サーバーからクライアントに送信されます。 |
Content-Length |
応答が圧縮されるときに本文の内容が変更されるため、圧縮が発生すると Content-Length ヘッダーが削除されます。 |
Content-MD5 |
圧縮が発生すると、本文の内容が変更されハッシュが無効になるので、Content-MD5 ヘッダーが削除されます。 |
Content-Type |
コンテンツの MIME の種類を指定します。 すべての応答で、その Content-Type を指定する必要があります。 応答圧縮ミドルウェアによりこの値がチェックされ、応答を圧縮する必要があるかどうかが判断されます。 応答圧縮ミドルウェアは、エンコードできる既定の MIME の種類 のセットを指定し、置き換えたり追加したりできます。 |
Vary |
サーバーにより Accept-Encoding の値でクライアントやプロキシに送信されると、Vary ヘッダーにより、クライアントやプロキシに対して、要求の Accept-Encoding ヘッダーの値に基づいて応答をキャッシュ (変化) させる必要があることが示されます。 Vary: Accept-Encoding ヘッダーを含むコンテンツを返すと、圧縮されている、および圧縮されていない応答の両方が別々にキャッシュされます。 |
サンプル アプリを使用して、応答圧縮ミドルウェアの機能を確認しましょう。 このサンプルでは次のことが説明されています。
- Gzip とカスタム圧縮プロバイダーを使用したアプリの応答の圧縮。
- 圧縮のために MIME の種類の既定の一覧に MIME の種類を追加する方法。
- カスタム応答圧縮プロバイダーを追加する方法。
構成
次のコードは、既定の MIME の種類 と圧縮プロバイダー (Brotli と Gzip) に対して応答圧縮ミドルウェアを有効にする方法を示しています:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddResponseCompression(options =>
{
options.EnableForHttps = true;
});
var app = builder.Build();
app.UseResponseCompression();
app.MapGet("/", () => "Hello World!");
app.Run();
注:
EnableForHttps
をtrue
に設定にすると、セキュリティ上のリスクとなります。 詳細については、この記事の 「HTTPS を使用した圧縮」を参照してください。app.UseResponseCompression
は、応答を圧縮するミドルウェアの前に呼び出す必要があります。 詳細については、「ASP.NET Core のミドルウェア」を参照してください。- Firefox Browser Developer などのツールを使って、
Accept-Encoding
要求ヘッダーを設定し、応答ヘッダー、サイズ、本文を調べます。
Accept-Encoding
ヘッダーなしでサンプル アプリに要求を送信し、応答が圧縮されていないことを確認します。 Content-Encoding
ヘッダーが応答ヘッダー コレクションに含まれていない。
たとえば、Firefox Developer では次のようになります:
- [ネットワーク] タブを選択します。
- [ネットワーク要求リスト] で要求を右クリックし、[編集して再送信] を選択します
Accept-Encoding:
をgzip, deflate, br
からnone
に変更します。- 送信を選択します。
開発者ツールを使用してブラウザーでサンプル アプリへの要求を送信して、応答が圧縮されていることを観察します。 Content-Encoding
と Vary
ヘッダーが応答に存在しています。
プロバイダー
Brotli および Gzip 圧縮プロバイダー
Brotli 圧縮データ形式で応答を圧縮するには BrotliCompressionProvider を使用します。
圧縮プロバイダーが CompressionProviderCollection に明示的に追加されていない場合:
- Brotli 圧縮プロバイダーと Gzip 圧縮プロバイダーは、既定で圧縮プロバイダーの配列に追加されます。
- クライアントで Brotli 圧縮データ形式がサポートされている場合、圧縮は既定で Brotli 圧縮になります。 Brotli がクライアントでサポートされておらず、Gzip 圧縮がクライアントでサポートされている場合、圧縮は既定で Gzip になります。
Note
通常、.NET 参照ソースへのドキュメント リンクを使用すると、リポジトリの既定のブランチが読み込まれます。このブランチは、.NET の次回リリースに向けて行われている現在の開発を表します。 特定のリリースのタグを選択するには、[Switch branches or tags](ブランチまたはタグの切り替え) ドロップダウン リストを使います。 詳細については、「ASP.NET Core ソース コードのバージョン タグを選択する方法」 (dotnet/AspNetCore.Docs #26205) を参照してください。
圧縮プロバイダーが追加されると、他のプロバイダーは追加されません。 たとえば、Gzip 圧縮プロバイダーが明示的に追加された唯一のプロバイダーである場合、他の圧縮プロバイダーは追加されません。
コード例を次に示します。
- HTTPS 要求の応答圧縮を有効にします。
- Brotli および Gzip 応答圧縮プロバイダーを追加します。
using System.IO.Compression;
using Microsoft.AspNetCore.ResponseCompression;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddResponseCompression(options =>
{
options.EnableForHttps = true;
options.Providers.Add<BrotliCompressionProvider>();
options.Providers.Add<GzipCompressionProvider>();
});
builder.Services.Configure<BrotliCompressionProviderOptions>(options =>
{
options.Level = CompressionLevel.Fastest;
});
builder.Services.Configure<GzipCompressionProviderOptions>(options =>
{
options.Level = CompressionLevel.SmallestSize;
});
var app = builder.Build();
app.UseResponseCompression();
app.MapGet("/", () => "Hello World!");
app.Run();
BrotliCompressionProviderOptions と GzipCompressionProviderOptions を使用して圧縮レベルを設定します。 Brotli 圧縮プロバイダーは、既定で最も高速な圧縮レベルである CompressionLevel.Fastest に設定されていますが、これでは、最も効率的に圧縮を生成できない場合があります。 最も効率的な圧縮が必要な場合は、最適な圧縮用に応答圧縮ミドルウェアを構成します。
圧縮操作で速度を重視するか、または圧縮サイズを重視するかを示す値については、「CompressionLevel 列挙型」を参照してください。
using System.IO.Compression;
using Microsoft.AspNetCore.ResponseCompression;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddResponseCompression(options =>
{
options.EnableForHttps = true;
options.Providers.Add<BrotliCompressionProvider>();
options.Providers.Add<GzipCompressionProvider>();
});
builder.Services.Configure<BrotliCompressionProviderOptions>(options =>
{
options.Level = CompressionLevel.Fastest;
});
builder.Services.Configure<GzipCompressionProviderOptions>(options =>
{
options.Level = CompressionLevel.SmallestSize;
});
var app = builder.Build();
app.UseResponseCompression();
app.MapGet("/", () => "Hello World!");
app.Run();
カスタム プロバイダー
ICompressionProviderを使用してカスタム圧縮実装を作成します。 EncodingName は、この ICompressionProvider
で生成されるコンテンツ エンコードを表します。 ミドルウェアは、この情報を使用して、要求の Accept-Encoding
ヘッダーで指定されたリストに基づいてプロバイダーを選択します。
Accept-Encoding: mycustomcompression
ヘッダーのあるサンプル アプリへの要求は Content-Encoding: mycustomcompression
ヘッダーのある応答を返します。 カスタム圧縮実装が機能するには、クライアントでカスタム エンコードを展開できる必要があります。
using Microsoft.AspNetCore.ResponseCompression;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddResponseCompression(options =>
{
options.Providers.Add<BrotliCompressionProvider>();
options.Providers.Add<GzipCompressionProvider>();
options.Providers.Add<CustomCompressionProvider>();
});
var app = builder.Build();
app.UseResponseCompression();
app.MapGet("/", () => "Hello World!");
app.Run();
using Microsoft.AspNetCore.ResponseCompression;
public class CustomCompressionProvider : ICompressionProvider
{
public string EncodingName => "mycustomcompression";
public bool SupportsFlush => true;
public Stream CreateStream(Stream outputStream)
{
// Replace with a custom compression stream wrapper.
return outputStream;
}
}
上記のコードでは、応答本文はサンプルによって圧縮されません。 しかし、このサンプルでは、カスタム圧縮アルゴリズムを実装する場所を示しています。
MIME タイプ
応答圧縮ミドルウェアにより、圧縮のために既定の MIME の種類のセットが指定されます。 サポートされている MIME の種類の完全なリストのソース コードを参照してください。
Note
通常、.NET 参照ソースへのドキュメント リンクを使用すると、リポジトリの既定のブランチが読み込まれます。このブランチは、.NET の次回リリースに向けて行われている現在の開発を表します。 特定のリリースのタグを選択するには、[Switch branches or tags](ブランチまたはタグの切り替え) ドロップダウン リストを使います。 詳細については、「ASP.NET Core ソース コードのバージョン タグを選択する方法」 (dotnet/AspNetCore.Docs #26205) を参照してください。
MME の種類を ResponseCompressionOptions.MimeTypes
で置き換えるか、追加します。 ワイルドカードの MIME の種類 (text/*
など) はサポートされていないことにご注意ください。 サンプル アプリでは、image/svg+xml
の MIME の種類が追加され、ASP.NET Core のバナー画像 banner.svg が圧縮されて提供されます。
using Microsoft.AspNetCore.ResponseCompression;
using ResponseCompressionSample;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddResponseCompression(options =>
{
options.EnableForHttps = true;
options.Providers.Add<BrotliCompressionProvider>();
options.Providers.Add<GzipCompressionProvider>();
options.Providers.Add<CustomCompressionProvider>();
options.MimeTypes =
ResponseCompressionDefaults.MimeTypes.Concat(
new[] { "image/svg+xml" });
});
var app = builder.Build();
app.UseResponseCompression();
Vary ヘッダーを追加する
Accept-Encoding
要求ヘッダーに基づいて応答を圧縮する場合、応答の圧縮されていないバージョンと圧縮されたバージョンが複数存在することがあります。 複数のバージョンが存在していることと、格納する必要があることをクライアントとプロキシのキャッシュに指示するため、Vary
ヘッダーに Accept-Encoding
の値が追加されます。 応答が圧縮された場合、応答ミドルウェアによって自動的にVary
ヘッダーが追加されます。
Note
通常、.NET 参照ソースへのドキュメント リンクを使用すると、リポジトリの既定のブランチが読み込まれます。このブランチは、.NET の次回リリースに向けて行われている現在の開発を表します。 特定のリリースのタグを選択するには、[Switch branches or tags](ブランチまたはタグの切り替え) ドロップダウン リストを使います。 詳細については、「ASP.NET Core ソース コードのバージョン タグを選択する方法」 (dotnet/AspNetCore.Docs #26205) を参照してください。
Nginx リバース プロキシの背後にある場合のミドルウェアの問題
要求が Nginx によってプロキシされると、Accept-Encoding
ヘッダーは削除されます。 Accept-Encoding
ヘッダーが削除されると、応答圧縮ミドルウェアで応答が圧縮されなくなります。 詳細については「NGINX: Compression and Decompression」(NGINX: 圧縮と展開) をご覧ください。 この問題は、「Nginx のパススルー圧縮を理解する (dotnet/aspnetcore#5989)」で追跡されています。
IIS 動的圧縮の無効化
サーバー レベルで構成された IIS 動的圧縮モジュールを無効にするには、「IIS モジュールの無効化」を参照してください。
応答圧縮のトラブルシューティング
Firefox Browser Developer などのツールを使って、Accept-Encoding
要求ヘッダーを設定し、応答ヘッダー、サイズ、本文を調べます。 既定では、次の条件を満たす応答が応答圧縮ミドルウェアにより圧縮されます。
br
、gzip
、*
の値または、カスタム圧縮プロバイダーに一致するカスタム エンコードがあるAccept-Encoding
ヘッダーが存在します。 値がidentity
ではない。また、設定が 0 (zero) の品質値 (qvalue、q
) がない。- MIME の種類 (
Content-Type
) が設定されていて ResponseCompressionOptions で構成されている MIME の種類と一致している。 - 要求に
Content-Range
ヘッダーが含まれない。 - 要求では、応答圧縮ミドルウェアのオプションで、セキュリティで保護されたプロトコル (https) が構成されている場合を除き、安全ではないプロトコル (http) を使用する必要がある。 セキュリティで保護されたコンテンツの圧縮を有効にする場合は、前述の危険性にご注意ください。
Azure デプロイ済みサンプル
Azure にデプロイされたサンプル アプリには、次の Program.cs
ファイルがあります:
using Microsoft.AspNetCore.ResponseCompression;
using ResponseCompressionSample;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddResponseCompression(options =>
{
options.EnableForHttps = true;
options.Providers.Add<BrotliCompressionProvider>();
options.Providers.Add<GzipCompressionProvider>();
options.Providers.Add<CustomCompressionProvider>();
options.MimeTypes =
ResponseCompressionDefaults.MimeTypes.Concat(
new[] { "image/svg+xml" });
});
var app = builder.Build();
app.UseResponseCompression();
app.Map("/trickle", async (HttpResponse httpResponse) =>
{
httpResponse.ContentType = "text/plain;charset=utf-8";
for (int i = 0; i < 20; i++)
{
await httpResponse.WriteAsync("a");
await httpResponse.Body.FlushAsync();
await Task.Delay(TimeSpan.FromMilliseconds(50));
}
});
app.Map("/testfile1kb.txt", () => Results.File(
app.Environment.ContentRootFileProvider.GetFileInfo("testfile1kb.txt").PhysicalPath,
"text/plain;charset=utf-8"));
app.Map("/banner.svg", () => Results.File(
app.Environment.ContentRootFileProvider.GetFileInfo("banner.svg").PhysicalPath,
"image/svg+xml;charset=utf-8"));
app.MapFallback(() => LoremIpsum.Text);
app.Run();
その他のリソース
Note
通常、.NET 参照ソースへのドキュメント リンクを使用すると、リポジトリの既定のブランチが読み込まれます。このブランチは、.NET の次回リリースに向けて行われている現在の開発を表します。 特定のリリースのタグを選択するには、[Switch branches or tags](ブランチまたはタグの切り替え) ドロップダウン リストを使います。 詳細については、「ASP.NET Core ソース コードのバージョン タグを選択する方法」 (dotnet/AspNetCore.Docs #26205) を参照してください。
ネットワーク帯域幅は限られたリソースです。 通常、応答のサイズを小さくすると、多くの場合、アプリの応答性が大幅に向上します。 ペイロード サイズを小さくする 1 つの方法は、アプリの応答を圧縮することです。
サンプル コードを表示またはダウンロードします (ダウンロード方法)。
応答圧縮ミドルウェアを使用する状況
IIS、Apache、または Nginx でサーバーベースの応答圧縮テクノロジを使用します。 ミドルウェアのパフォーマンスは、おそらくモジュールのそれには及びません。 HTTP.sys サーバー と Kestrel サーバーでは、現在、組み込みの圧縮サポートは提供されていません。
応答圧縮ミドルウェアは次のような場合に使用します。
- 次のサーバーベースの圧縮テクノロジを使用できない。
- 次で直接ホスティングしている。
- HTTP.sys サーバー (以前の WebListener)
- Kestrel サーバー
応答圧縮
通常、ネイティブに圧縮されていない応答は、応答の圧縮のベネフィットを受ける可能性があります。 ネイティブに圧縮されていない応答には、一般的に CSS、JavaScript、HTML、XML、JSON が含まれます。 PNG ファイルなどのネイティブに圧縮されているアセットは圧縮すべきではありません。 ネイティブに圧縮されている応答をさらに圧縮しようとすると、サイズや転送時間がさらにわずかに減少しても、圧縮の処理にかかった時間のために意味がなくなってしまうことがあります。 約 150 から 1,000 バイト未満 (ファイルの内容と圧縮の効率により異なる) のファイルは圧縮しないようにしてください。 小さいファイルを圧縮するオーバーヘッドにより、圧縮されていないファイルよりも大きい圧縮ファイルが生成される場合があります。
クライアントが圧縮されたコンテンツを処理できる場合、クライアントは Accept-Encoding
ヘッダーを要求と一緒に送信して、その機能をサーバーに通知する必要があります。 サーバーにより圧縮されたコンテンツが送信されるときには、圧縮された応答のエンコード方法に関する情報を Content-Encoding
ヘッダーに含める必要があります。 次の表に、ミドルウェアによりサポートされているコンテンツ エンコードの指定を示します。
Accept-Encoding ヘッダー値 |
ミドルウェアによるサポート | 説明 |
---|---|---|
br |
可 (既定) | Brotli 圧縮データ形式 |
deflate |
いいえ | DEFLATE 圧縮データ形式 |
exi |
いいえ | W3C 効率的な XML 交換形式 |
gzip |
はい | Gzip ファイル形式 |
identity |
はい | "エンコードなし" の識別子: 応答をエンコードできません。 |
pack200-gzip |
いいえ | Network Transfer Format for Java Archives |
* |
はい | 明示的に要求されていない、すべての使用可能なコンテンツ エンコード |
詳細については、「IANA Official Content Coding List」(IANA 公式コンテンツ コーディング リスト) をご覧ください。
ミドルウェアを使用すると、カスタム Accept-Encoding
ヘッダー値の圧縮プロバイダーを追加できます。 詳細については、下記の「カスタム プロバイダー」をご覧ください。
ミドルウェアは、クライアントからの送信時に、品質値 (qvalue q
) の重み付けに反応して圧縮スキームの優先度付けを行うことができます。 詳細については『RFC 9110: Accept-Encoding』をご覧ください。
圧縮アルゴリズムは、圧縮速度と圧縮の有効性のトレードオフの対象になります。 ここでの 有効性 は、圧縮後の出力のサイズを指します。 最小サイズは、最適 な圧縮によって実現します。
圧縮されたコンテンツの要求、送信、キャッシュ、受信に関連するヘッダーを次の表に示します。
ヘッダー | Role |
---|---|
Accept-Encoding |
クライアントが受け入れ可能なコンテンツ エンコード方式を示すために、クライアントからサーバーに送信されます。 |
Content-Encoding |
ペイロード内のコンテンツのエンコードを示すために、サーバーからクライアントに送信されます。 |
Content-Length |
応答が圧縮されるときに本文の内容が変更されるため、圧縮が発生すると Content-Length ヘッダーが削除されます。 |
Content-MD5 |
圧縮が発生すると、本文の内容が変更されハッシュが無効になるので、Content-MD5 ヘッダーが削除されます。 |
Content-Type |
コンテンツの MIME の種類を指定します。 すべての応答で、その Content-Type を指定する必要があります。 ミドルウェアによりこの値がチェックされ、応答を圧縮する必要があるかどうかが判断されます。 ミドルウェアで、エンコードできる既定の MIME の種類のセットが指定されますが、MIME の種類を置き換えるかまたは追加することもできます。 |
Vary |
サーバーにより Accept-Encoding の値でクライアントやプロキシに送信されると、Vary ヘッダーにより、クライアントやプロキシに対して、要求の Accept-Encoding ヘッダーの値に基づいて応答をキャッシュ (変化) させる必要があることが示されます。 Vary: Accept-Encoding ヘッダーを含むコンテンツを返すと、圧縮されている、および圧縮されていない応答の両方が別々にキャッシュされます。 |
サンプル アプリを使用して、応答圧縮ミドルウェアの機能を確認しましょう。 このサンプルでは次のことが説明されています。
- Gzip とカスタム圧縮プロバイダーを使用したアプリの応答の圧縮。
- 圧縮のために MIME の種類の既定の一覧に MIME の種類を追加する方法。
構成
次のコードは、既定の MIME の種類 と圧縮プロバイダー (Brotli と Gzip) に対して応答圧縮ミドルウェアを有効にする方法を示しています:
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddResponseCompression();
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
app.UseResponseCompression();
}
}
注:
app.UseResponseCompression
は、応答を圧縮するミドルウェアの前に呼び出す必要があります。 詳細については、「ASP.NET Core のミドルウェア」を参照してください。- Fiddler、Firefox Browser Developer などのツールを使って、
Accept-Encoding
要求ヘッダーを設定し、応答ヘッダー、サイズ、本文を調べます。
Accept-Encoding
ヘッダーなしでサンプル アプリに要求を送信し、応答が圧縮されていないことを確認します。 Content-Encoding
と Vary
ヘッダーは応答に存在しません。
Accept-Encoding: br
ヘッダー (Brotli 圧縮) を含めた要求をサンプル アプリに送信し、応答が圧縮されていることを確認します。 Content-Encoding
と Vary
ヘッダーが応答に存在しています。
プロバイダー
Brotli 圧縮プロバイダー
Brotli 圧縮データ形式で応答を圧縮するには BrotliCompressionProvider を使用します。
圧縮プロバイダーが CompressionProviderCollection に明示的に追加されていない場合:
- Brotli 圧縮プロバイダーは、Gzip 圧縮プロバイダーと共に、既定で圧縮プロバイダーの配列に追加されています。
- クライアントで Brotli 圧縮データ形式がサポートされている場合、圧縮は既定で Brotli 圧縮になります。 Brotli がクライアントでサポートされておらず、Gzip 圧縮がクライアントでサポートされている場合、圧縮は既定で Gzip になります。
public void ConfigureServices(IServiceCollection services)
{
services.AddResponseCompression();
}
任意の圧縮プロバイダーを明示的に追加する場合に、Brotli 圧縮プロバイダーを追加する必要があります。
public void ConfigureServices(IServiceCollection services)
{
services.AddResponseCompression(options =>
{
options.Providers.Add<BrotliCompressionProvider>();
options.Providers.Add<GzipCompressionProvider>();
options.Providers.Add<CustomCompressionProvider>();
options.MimeTypes =
ResponseCompressionDefaults.MimeTypes.Concat(
new[] { "image/svg+xml" });
});
}
BrotliCompressionProviderOptions を使用して圧縮レベルを設定します。 Brotli 圧縮プロバイダーは、既定で最も高速な圧縮レベル (CompressionLevel) に設定されていますが、これは、最も効率的に圧縮を生成できない場合があります。 最も効率的な圧縮が必要な場合は、最適な圧縮用にミドルウェアを構成します。
圧縮レベル | 説明 |
---|---|
CompressionLevel.Fastest | 圧縮後のファイルが最適な圧縮ではなくても、操作はできるだけ迅速に完了する必要がある場合。 |
CompressionLevel.NoCompression | ファイルに対して圧縮は行われません。 |
CompressionLevel.Optimal | 圧縮が完了するまでに時間がかかる場合でも、応答が最適に圧縮される必要がある場合。 |
public void ConfigureServices(IServiceCollection services)
{
services.AddResponseCompression();
services.Configure<BrotliCompressionProviderOptions>(options =>
{
options.Level = CompressionLevel.Fastest;
});
}
Gzip 圧縮プロバイダー
GzipCompressionProvider を使用して、応答を Gzip ファイル形式で圧縮します。
圧縮プロバイダーが CompressionProviderCollection に明示的に追加されていない場合:
- Gzip 圧縮プロバイダーは、Brotli 圧縮プロバイダーと共に、既定で圧縮プロバイダーの配列に追加されています。
- クライアントで Brotli 圧縮データ形式がサポートされている場合、圧縮は既定で Brotli 圧縮になります。 Brotli がクライアントでサポートされておらず、Gzip 圧縮がクライアントでサポートされている場合、圧縮は既定で Gzip になります。
public void ConfigureServices(IServiceCollection services)
{
services.AddResponseCompression();
}
任意の圧縮プロバイダーを明示的に追加する場合に、Gzip 圧縮プロバイダーを追加する必要があります。
public void ConfigureServices(IServiceCollection services)
{
services.AddResponseCompression(options =>
{
options.Providers.Add<BrotliCompressionProvider>();
options.Providers.Add<GzipCompressionProvider>();
options.Providers.Add<CustomCompressionProvider>();
options.MimeTypes =
ResponseCompressionDefaults.MimeTypes.Concat(
new[] { "image/svg+xml" });
});
}
GzipCompressionProviderOptions を使用して圧縮レベルを設定します。 Gzip 圧縮プロバイダーは、既定で最も高速な圧縮レベル (CompressionLevel) に設定されていますが、これは、最も効率的に圧縮を生成できない場合があります。 最も効率的な圧縮が必要な場合は、最適な圧縮用にミドルウェアを構成します。
圧縮レベル | 説明 |
---|---|
CompressionLevel.Fastest | 圧縮後のファイルが最適な圧縮ではなくても、操作はできるだけ迅速に完了する必要がある場合。 |
CompressionLevel.NoCompression | ファイルに対して圧縮は行われません。 |
CompressionLevel.Optimal | 圧縮が完了するまでに時間がかかる場合でも、応答が最適に圧縮される必要がある場合。 |
public void ConfigureServices(IServiceCollection services)
{
services.AddResponseCompression();
services.Configure<GzipCompressionProviderOptions>(options =>
{
options.Level = CompressionLevel.Fastest;
});
}
カスタム プロバイダー
ICompressionProviderを使用してカスタム圧縮実装を作成します。 EncodingName は、この ICompressionProvider
で生成されるコンテンツ エンコードを表します。 ミドルウェアは、この情報を使用して、要求の Accept-Encoding
ヘッダーで指定された一覧に基づいてプロバイダーを選択します。
サンプル アプリを使用して、クライアントにより Accept-Encoding: mycustomcompression
ヘッダーを使って要求が送信されます。 ミドルウェアにより、カスタム圧縮実装が使用され、Content-Encoding: mycustomcompression
ヘッダーを含む応答が返されます。 カスタム圧縮実装が機能するには、クライアントでカスタム エンコードを展開できる必要があります。
public void ConfigureServices(IServiceCollection services)
{
services.AddResponseCompression(options =>
{
options.Providers.Add<BrotliCompressionProvider>();
options.Providers.Add<GzipCompressionProvider>();
options.Providers.Add<CustomCompressionProvider>();
options.MimeTypes =
ResponseCompressionDefaults.MimeTypes.Concat(
new[] { "image/svg+xml" });
});
}
public class CustomCompressionProvider : ICompressionProvider
{
public string EncodingName => "mycustomcompression";
public bool SupportsFlush => true;
public Stream CreateStream(Stream outputStream)
{
// Create a custom compression stream wrapper here
return outputStream;
}
}
Accept-Encoding: mycustomcompression
ヘッダーを含めた要求をサンプル アプリに送信し、応答ヘッダーを確認します。 Vary
と Content-Encoding
ヘッダーが応答に存在しています。 このサンプルでは、応答本文 (表示されていません) は圧縮されません。 サンプルの CustomCompressionProvider
クラスに圧縮の実装は含まれていません。 しかし、このサンプルでは、このような圧縮アルゴリズムを実装する場所を示しています。
MIME タイプ
ミドルウェアにより、圧縮のために既定の MIME の種類のセットが指定されます。
application/javascript
application/json
application/xml
text/css
text/html
text/json
text/plain
text/xml
応答圧縮ミドルウェアのオプションを使用して、MIME の種類を置換または追加します。 ワイルドカードの MIME の種類 (text/*
など) はサポートされていないことにご注意ください。 サンプル アプリでは、image/svg+xml
の MIME の種類が追加され、ASP.NET Core のバナー画像 (banner.svg ) が圧縮されて提供されます。
public void ConfigureServices(IServiceCollection services)
{
services.AddResponseCompression(options =>
{
options.Providers.Add<BrotliCompressionProvider>();
options.Providers.Add<GzipCompressionProvider>();
options.Providers.Add<CustomCompressionProvider>();
options.MimeTypes =
ResponseCompressionDefaults.MimeTypes.Concat(
new[] { "image/svg+xml" });
});
}
セキュリティで保護されたプロトコルを使用した圧縮
セキュリティで保護された接続での圧縮された応答は、EnableForHttps
オプションで制御できますが、これは既定では無効になっています。 動的に生成されたページで圧縮を使用すると、CRIME や BREACH 攻撃などのセキュリティの問題が発生するおそれがあります。
Vary ヘッダーを追加する
Accept-Encoding
ヘッダーに基づいて応答を圧縮する場合、応答の圧縮されたバージョンと圧縮されていないバージョンが複数存在することがあります。 複数のバージョンが存在していることと、格納する必要があることをクライアントとプロキシのキャッシュに指示するため、Vary
ヘッダーに Accept-Encoding
の値が追加されます。 ASP.NET Core 2.0 以降では、応答が圧縮された場合、ミドルウェアによって Vary
ヘッダーが自動的に追加されます。
Nginx リバース プロキシの背後にある場合のミドルウェアの問題
要求が Nginx によってプロキシされると、Accept-Encoding
ヘッダーは削除されます。 Accept-Encoding
ヘッダーが削除されると、ミドルウェアで応答が圧縮されなくなります。 詳細については「NGINX: Compression and Decompression」(NGINX: 圧縮と展開) をご覧ください。 この問題は、「Nginx のパススルー圧縮を理解する (dotnet/aspnetcore#5989)」で追跡されています。
IIS 動的圧縮の使用
サーバー レベルで構成されたアクティブな IIS 動的圧縮モジュールがあり、アプリに対して無効にする場合は、web.config ファイルに追加するとモジュールが無効になります。 詳細については、「Disabling IIS modules」 (IIS モジュールの無効化) を参照してください。
トラブルシューティング
Fiddler や Firefox Browser Developer などのツールを使って、Accept-Encoding
要求ヘッダーを設定し、応答ヘッダー、サイズ、本文を調べます。 既定では、次の条件を満たす応答が応答圧縮ミドルウェアにより圧縮されます。
Accept-Encoding
ヘッダーとともに、br
、gzip
、*
の値、またはユーザーが設定したカスタム圧縮プロバイダーに一致するカスタム エンコードが含まれている。 値がidentity
ではない。また、設定が 0 (zero) の品質値 (qvalue、q
) がない。- MIME の種類 (
Content-Type
) が設定されていて ResponseCompressionOptions で構成されている MIME の種類と一致している。 - 要求に
Content-Range
ヘッダーが含まれない。 - 要求では、応答圧縮ミドルウェアのオプションで、セキュリティで保護されたプロトコル (https) が構成されている場合を除き、安全ではないプロトコル (http) を使用する必要がある。 セキュリティで保護されたコンテンツの圧縮を有効にする場合は、前述の危険性にご注意ください。
その他のリソース
ASP.NET Core