ASP.NET Core での応答の圧縮

ネットワーク帯域幅は限られたリソースです。 通常、応答のサイズを小さくすると、多くの場合、アプリの応答性が大幅に向上します。 ペイロード サイズを小さくする 1 つの方法は、アプリの応答を圧縮することです。

HTTPS を使用した圧縮

セキュリティで保護された接続での圧縮された応答は、EnableForHttps オプションで制御できますが、セキュリティ リスクがあるため、既定では無効になっています。 動的に生成されたページで圧縮を使用すると、CRIMEBREACH 攻撃にアプリが公開される可能性があります。 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();

注:

  • EnableForHttpstrue に設定にすると、セキュリティ上のリスクとなります。 詳細については、この記事の 「HTTPS を使用した圧縮」を参照してください。
  • app.UseResponseCompression は、応答を圧縮するミドルウェアの前に呼び出す必要があります。 詳細については、「ASP.NET Core のミドルウェア」を参照してください。
  • Firefox Browser Developer などのツールを使って、Accept-Encoding 要求ヘッダーを設定し、応答ヘッダー、サイズ、本文を調べます。

Accept-Encoding ヘッダーなしでサンプル アプリに要求を送信し、応答が圧縮されていないことを確認します。 Content-Encoding ヘッダーが応答ヘッダー コレクションに含まれていない。

たとえば、Firefox Developer では次のようになります:

  • [ネットワーク] タブを選択します。
  • [ネットワーク要求リスト] で要求を右クリックし、[編集して再送信] を選択します
  • Accept-Encoding:gzip, deflate, br から none に変更します。
  • 送信を選択します。

開発者ツールを使用してブラウザーでサンプル アプリへの要求を送信して、応答が圧縮されていることを観察します。 Content-EncodingVary ヘッダーが応答に存在しています。

プロバイダー

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();

BrotliCompressionProviderOptionsGzipCompressionProviderOptions を使用して圧縮レベルを設定します。 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 要求ヘッダーを設定し、応答ヘッダー、サイズ、本文を調べます。 既定では、次の条件を満たす応答が応答圧縮ミドルウェアにより圧縮されます。

  • brgzip* の値または、カスタム圧縮プロバイダーに一致するカスタム エンコードがある 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 サーバーでは、現在、組み込みの圧縮サポートは提供されていません。

応答圧縮ミドルウェアは次のような場合に使用します。

応答圧縮

通常、ネイティブに圧縮されていない応答は、応答の圧縮のベネフィットを受ける可能性があります。 ネイティブに圧縮されていない応答には、一般的に 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 のミドルウェア」を参照してください。
  • FiddlerFirefox Browser Developer などのツールを使って、Accept-Encoding 要求ヘッダーを設定し、応答ヘッダー、サイズ、本文を調べます。

Accept-Encoding ヘッダーなしでサンプル アプリに要求を送信し、応答が圧縮されていないことを確認します。 Content-EncodingVary ヘッダーは応答に存在しません。

Fiddler window showing result of a request without the Accept-Encoding header. The response isn't compressed.

Accept-Encoding: br ヘッダー (Brotli 圧縮) を含めた要求をサンプル アプリに送信し、応答が圧縮されていることを確認します。 Content-EncodingVary ヘッダーが応答に存在しています。

Fiddler window showing result of a request with the Accept-Encoding header and a value of br. The Vary and Content-Encoding headers are added to the response. The response is compressed.

プロバイダー

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 ヘッダーを含めた要求をサンプル アプリに送信し、応答ヘッダーを確認します。 VaryContent-Encoding ヘッダーが応答に存在しています。 このサンプルでは、応答本文 (表示されていません) は圧縮されません。 サンプルの CustomCompressionProvider クラスに圧縮の実装は含まれていません。 しかし、このサンプルでは、このような圧縮アルゴリズムを実装する場所を示しています。

Fiddler window showing result of a request with the Accept-Encoding header and a value of mycustomcompression. The Vary and Content-Encoding headers are added to the response.

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 オプションで制御できますが、これは既定では無効になっています。 動的に生成されたページで圧縮を使用すると、CRIMEBREACH 攻撃などのセキュリティの問題が発生するおそれがあります。

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 モジュールの無効化) を参照してください。

トラブルシューティング

FiddlerFirefox Browser Developer などのツールを使って、Accept-Encoding 要求ヘッダーを設定し、応答ヘッダー、サイズ、本文を調べます。 既定では、次の条件を満たす応答が応答圧縮ミドルウェアにより圧縮されます。

  • Accept-Encoding ヘッダーとともに、brgzip* の値、またはユーザーが設定したカスタム圧縮プロバイダーに一致するカスタム エンコードが含まれている。 値が identity ではない。また、設定が 0 (zero) の品質値 (qvalue、q) がない。
  • MIME の種類 (Content-Type) が設定されていて ResponseCompressionOptions で構成されている MIME の種類と一致している。
  • 要求に Content-Range ヘッダーが含まれない。
  • 要求では、応答圧縮ミドルウェアのオプションで、セキュリティで保護されたプロトコル (https) が構成されている場合を除き、安全ではないプロトコル (http) を使用する必要がある。 セキュリティで保護されたコンテンツの圧縮を有効にする場合は、前述の危険性にご注意ください。

その他のリソース