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、ON JSが含まれます。 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 7231: Accept-Encoding」をご覧ください。

圧縮アルゴリズムは、圧縮速度と圧縮の有効性のトレードオフの対象になります。 ここでの 有効性 は、圧縮後の出力のサイズを指します。 最小サイズは、最適な圧縮によって実現されます。

次の表では、圧縮コンテンツの要求、送信、キャッシュ、および受信に関連するヘッダーについて説明します。

ヘッダー ロール
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();

メモ:

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

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

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

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

プロバイダー

Brotli および Gzip 圧縮プロバイダー

Brotli 圧縮データ形式で応答を圧縮するには BrotliCompressionProvider を使用します。

圧縮プロバイダーが明示的に追加されていない場合は、次のコマンドを実行CompressionProviderCollectionします。

  • Brotli 圧縮プロバイダーと Gzip 圧縮プロバイダーは、既定で圧縮プロバイダーの配列に追加されます。
  • クライアントで Brotli 圧縮データ形式がサポートされている場合、圧縮は既定で Brotli 圧縮になります。 Brotli がクライアントでサポートされておらず、Gzip 圧縮がクライアントでサポートされている場合、圧縮は既定で Gzip になります。

注意

通常、.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 および Gzip 圧縮プロバイダーは、既定で最も高速な圧縮レベル である CompressionLevel.Fastest に設定され、最も効率的な圧縮が生成されない可能性があります。 最も効率的な圧縮が必要な場合は、最適な圧縮のために応答圧縮ミドルウェアを構成します。

Compression Level 説明
CompressionLevel.Fastest 圧縮後のファイルが最適な圧縮ではなくても、操作はできるだけ迅速に完了する必要がある場合。
CompressionLevel.NoCompression ファイルに対して圧縮は行われません。
CompressionLevel.Optimal 圧縮が完了するまでに時間がかかる場合でも、応答が最適に圧縮される必要がある場合。
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 の種類の完全な一覧については、ソース コードを参照してください。

注意

通常、.NET 参照ソースへのドキュメント リンクを使用すると、リポジトリの既定のブランチが読み込まれます。このブランチは、.NET の次回リリースに向けて行われている現在の開発を表します。 特定のリリースのタグを選択するには、[Switch branches or tags](ブランチまたはタグの切り替え) ドロップダウン リストを使います。 詳細については、「ASP.NET Core ソース コードのバージョン タグを選択する方法」 (dotnet/AspNetCore.Docs #26205) を参照してください。

MIME の種類を次のように置き ResponseCompressionOptions.MimeTypes換えるか追加します。 ワイルドカードの MIME の種類 (text/* など) はサポートされていないことにご注意ください。 サンプル アプリは、MIME の種類をimage/svg+xml追加して圧縮し、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圧縮されるときにヘッダーを自動的に追加します。

注意

通常、.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 DeveloperPostman などのツールを使用します。これにより、要求ヘッダーをAccept-Encoding設定し、応答ヘッダー、サイズ、本文を調べることができます。 既定では、次の条件を満たす応答が応答圧縮ミドルウェアにより圧縮されます。

  • ヘッダーには Accept-Encoding 、カスタム圧縮プロバイダーに一致する値 brgzip*またはカスタム エンコードが指定されています。 値が 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();

その他の技術情報

注意

通常、.NET 参照ソースへのドキュメント リンクを使用すると、リポジトリの既定のブランチが読み込まれます。このブランチは、.NET の次回リリースに向けて行われている現在の開発を表します。 特定のリリースのタグを選択するには、[Switch branches or tags](ブランチまたはタグの切り替え) ドロップダウン リストを使います。 詳細については、「ASP.NET Core ソース コードのバージョン タグを選択する方法」 (dotnet/AspNetCore.Docs #26205) を参照してください。

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

サンプル コードを表示またはダウンロードします (ダウンロード方法)。

応答圧縮ミドルウェアを使用する状況

IIS、Apache、または Nginx でサーバーベースの応答圧縮テクノロジを使用します。 ミドルウェアのパフォーマンスは、おそらくモジュールのそれには及びません。 HTTP.sys サーバーKestrel サーバーでは、現在、組み込みの圧縮サポートは提供されていません。

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

応答圧縮

通常、ネイティブに圧縮されていない応答は、応答の圧縮のベネフィットを受ける可能性があります。 通常、ネイティブに圧縮されない応答には、CSS、JavaScript、HTML、XML、ON JSが含まれます。 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 7231: Accept-Encoding」をご覧ください。

圧縮アルゴリズムは、圧縮速度と圧縮の有効性のトレードオフの対象になります。 ここでの 有効性 は、圧縮後の出力のサイズを指します。 最小サイズは、最適 な圧縮によって実現します。

圧縮されたコンテンツの要求、送信、キャッシュ、受信に関連するヘッダーを次の表に示します。

ヘッダー ロール
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 の種類と圧縮プロバイダー (BrotliGzip) に対して応答圧縮ミドルウェアを有効にする方法を示しています。

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 ブラウザー DeveloperPostman などのツールを使用して、Accept-Encoding 要求ヘッダーを設定し、応答ヘッダー、サイズ、本文を調べます。

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

Accept-Encoding ヘッダーのない要求の結果を示す Fiddler ウィンドウ。応答は圧縮されません。

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

Accept-Encoding ヘッダーと br の値を持つ要求の結果を示す Fiddler ウィンドウ。Vary ヘッダーと Content-Encoding ヘッダーが応答に追加されます。応答は圧縮されます。

プロバイダー

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) に設定されていますが、これは、最も効率的に圧縮を生成できない場合があります。 最も効率的な圧縮が必要な場合は、最適な圧縮用にミドルウェアを構成します。

Compression Level 説明
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) に設定されていますが、これは、最も効率的に圧縮を生成できない場合があります。 最も効率的な圧縮が必要な場合は、最適な圧縮用にミドルウェアを構成します。

Compression Level 説明
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 クラスに圧縮の実装は含まれていません。 しかし、このサンプルでは、このような圧縮アルゴリズムを実装する場所を示しています。

Accept-Encoding ヘッダーと mycustomcompression の値を含む要求の結果を示す Fiddler ウィンドウ。Vary ヘッダーと Content-Encoding ヘッダーが応答に追加されます。

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

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

その他の技術情報