Сжатие ответов в ASP.NET Core

Пропускная способность сети — это ограниченный ресурс. Уменьшение размера ответа обычно увеличивает скорость реагирования приложения, часто резко. Одним из способов уменьшения размера полезных данных является сжатие ответов из приложения. В этой статье описано, как реализовать сжатие откликов в ваших приложениях с помощью промежуточного ПО для сжатия откликов в ASP.NET Core.

Изучение сжатия с помощью HTTPS

Сжатые ответы по защищенным подключениям можно контролировать с помощью параметра EnableForHttps, который по умолчанию отключен из-за риска безопасности. Использование сжатия с динамически генерируемыми страницами может подвергать приложение атакам CRIME и BREACH. CRIME и BREACH атаки можно устранить в ASP.NET Core с помощью маркеров защиты от подделки. Дополнительные сведения см. на странице Предотвращение атак с использованием подделки межсайтовых запросов (XSRF/CSRF) в ASP.NET Core. Сведения о методах снижения риска атак см. в разделе BREACH на .

Даже если приложение отключает свойство EnableForHttps (false), Internet Information Services (IIS), IIS Express и Служба приложений Azure может применять Gzip на веб-сервере IIS. При просмотре заголовков ответов запишите значение заголовка Сервера. Непредвиденное значение заголовка ответа content-encoding может быть результатом веб-сервера, а не конфигурацией приложения ASP.NET Core.

Определите, когда использовать промежуточное ПО для сжатия ответов

Используйте серверные технологии сжатия ответов в IIS, Apache или Nginx. Производительность ПО промежуточного слоя сжатия ответа, вероятно, не может соответствовать производительности модулей сервера. Сервер HTTP.sys и Kestrel сервер в настоящее время не предлагают встроенную поддержку сжатия.

Используйте промежуточное ПО для сжатия ответов, если приложение:

Изучение сжатия ответов

Как правило, любой ответ, не являющийся изначально сжатым, может выиграть от сжатия ответа. Ответы, не сжатые в собственном коде, обычно включают CSS, JavaScript, HTML, XML и JSON. Не сжимайте собственные сжатые ресурсы, такие как PNG-файлы. При попытке дальнейшего сжатия исходно сжатого отклика небольшое дополнительное уменьшение объема и времени передачи, скорее всего, будет компенсировано временем, необходимым на обработку сжатия. Не сжимайте файлы меньше 150 – 1000 байт, в зависимости от содержимого файла и эффективности сжатия. Затраты на сжатие небольших файлов могут привести к тому, что сжатый файл больше, чем несжатый файл.

Когда клиент может обрабатывать сжатый контент, клиент должен сообщить серверу о своих возможностях, отправив заголовок Accept-Encoding с запросом. Когда сервер отправляет сжатое содержимое, он должен содержать сведения в заголовке "Кодирование содержимого " относительно кодирования сжатого ответа.

В следующей таблице показаны обозначения форматов кодировки содержимого для заголовка Accept-Encoding и указано, поддерживается ли это обозначение промежуточным программным обеспечением сжатия ответов.

Назначение Middleware Формат Сведения
br Да (по умолчанию) Формат сжатых данных Brotli RFC 7932
deflate No Формат данных, сжатых методом DEFLATE RFC 1951
exi No Эффективный обмен XML (EXI) Рекомендация W3C
gzip Yes Формат файла Gzip RFC 1952
identity Yes "Без кодирования" — ответ не должен быть закодирован Устранение неполадок с сжатием ответов
pack200-gzip No Формат передачи сети для архивов Java JSR 200
* (звездочка) Yes "Подстановочный знак" — любая доступная кодировка содержимого не запрашивается явно Устранение неполадок с сжатием ответов
Назначение Middleware Формат Сведения
br Да (по умолчанию) Формат сжатых данных Brotli RFC 7932
deflate No Формат данных, сжатых методом DEFLATE RFC 1951
exi No Эффективный обмен XML (EXI) Рекомендация W3C
gzip Yes Формат файла Gzip RFC 1952
identity Yes "Без кодирования" — ответ не должен быть закодирован Устранение неполадок с сжатием ответов
pack200-gzip No Формат передачи сети для архивов Java JSR 200
zstd Да (по умолчанию) Формат сжатых данных Zstandard RFC 8878
* (звездочка) Yes "Подстановочный знак" — любая доступная кодировка содержимого не запрашивается явно Устранение неполадок с сжатием ответов

Дополнительные сведения см. в списке кодирования официального содержимого IANA для параметров HTTP.

Промежуточный слой сжатия ответа позволяет добавлять других поставщиков сжатия для пользовательских Accept-Encoding значений заголовков. Для получения дополнительной информации см. Custom Providers далее в этой статье.

Промежуточное ПО для сжатия ответа может реагировать на значение качества (qvalue, q) и его вес при отправке клиентом для приоритезации схем сжатия. Дополнительные сведения см. в статье RFC 9110: семантика HTTP (раздел 12.5.3 Accept-Encoding).

Алгоритмы сжатия подвергаются компромиссу между скоростью сжатия и эффективностью сжатия. Эффективность в этом контексте относится к размеру выходных данных после сжатия. Наименьший размер достигается оптимальным сжатием.

Заголовки, участвующие в запросе, отправке, кэшировании и получении сжатого содержимого, описаны в следующей таблице.

Header Role Сведения
Accept-Encoding Отправляется от клиента на сервер, чтобы указать схемы кодирования содержимого, приемлемые для клиента. заголовок Accept-Encoding
Content-Encoding Отправляется с сервера на клиент, чтобы указать кодировку содержимого в теле сообщения. Заголовок кодирования содержимого
Content-Length При сжатии заголовок Content-Length удаляется, так как содержимое тела изменяется при сжатии ответа. Заголовок Content-Length
Content-MD5 При сжатии заголовок Content-MD5 удаляется, поскольку содержимое тела изменяется и хэш становится недействительным. RFC 1864: поле заголовка Content-MD5
Content-Type Указывает тип MIME содержимого. Каждый ответ должен указывать его Content-Type значение. ПО промежуточного слоя сжатия ответа проверяет это значение, чтобы определить, следует ли сжать ответ. ПО промежуточного слоя сжатия ответа указывает набор типов MIME по умолчанию , которые он может кодировать, и их можно заменить или добавить. Заголовок Content-Type
Vary При отправке сервером значения Accept-Encoding клиентам и прокси-серверам, заголовок Vary указывает клиенту или прокси-серверу, что он должен кэшировать (варьировать) ответы в зависимости от значения заголовка Accept-Encoding в запросе. Результат возврата содержимого с Vary: Accept-Encoding заголовком заключается в том, что сжатые и несжатые ответы кэшируются отдельно. Различаемый заголовок

Ознакомьтесь с возможностями промежуточного ПО для сжатия ответов с помощью примера приложения. Пример иллюстрирует следующее:

  • Сжатие ответов приложения с помощью Gzip и кастомных поставщиков сжатия.
  • Как добавить тип MIME в список типов MIME по умолчанию для сжатия.
  • Как добавить настраиваемого поставщика сжатия ответов.

Настройте промежуточное ПО для сжатия ответов

В следующем коде показано, как включить ПО промежуточного слоя сжатия ответов для типов MIME по умолчанию и поставщиков сжатия (Brotli и Gzip):

В следующем коде показано, как включить ПО промежуточного слоя сжатия ответов для типов MIME по умолчанию и поставщиков сжатия (Brotli, Gzip и Zstandard):

Заметки о промежуточном ПО для сжатия ответов

При работе с ПО промежуточного слоя сжатия ответов следует учитывать следующие моменты:

Отправьте запрос в пример приложения без заголовка Accept-Encoding и обратите внимание, что ответ не сжат. Заголовок Content-Encoding не содержится в коллекции заголовков ответа.

Например, в Firefox Developer:

  1. Выберите сетевую вкладку.
  2. Щелкните правой кнопкой мыши запрос в списке сетевых запросов и выберите "Изменить" и повторно отправить его.
  3. Измените значение параметра Accept-Encoding: с gzip, deflate, br на none.
  4. Нажмите кнопку "Отправить".

Отправьте запрос в пример приложения с браузером с помощью средств разработчика и обратите внимание, что ответ сжимается. На ответе присутствуют заголовки Content-Encoding и Vary.

Проверка поставщиков

В этом разделе содержатся сведения о поставщиках сжатия, включая Brotli, Gzip и пользовательских поставщиков.

В этом разделе содержатся сведения о поставщиках сжатия, включая Brotli, Gzip, Zstandard и пользовательских поставщиков.

Поставщики сжатия Brotli и Gzip

Используйте класс BrotliCompressionProvider для сжатия ответов в формате сжатых данных Brotli согласно RFC 7932.

Если поставщики сжатия явно не добавляются в CompressionProviderCollection класс:

  • По умолчанию поставщики сжатия Brotli и Gzip добавляются в массив поставщиков сжатия.
  • Когда клиент поддерживает формат сжатых данных Brotli, по умолчанию используется сжатие Brotli.
  • Если клиент не поддерживает Brotli, сжатие по умолчанию используется для Gzip, если клиент поддерживает сжатие Gzip.
  • По умолчанию поставщики сжатия Brotli, Gzip и Zstandard добавляются в массив поставщиков сжатия.
  • Если клиент поддерживает формат сжатия данных Zstandard, по умолчанию используется сжатие Zstandard.
  • Если клиент не поддерживает Zstandard, но поддерживает Brotli, сжатие по умолчанию используется для сжатия Brotli.
  • Если клиент не поддерживает Zstandard или Brotli, сжатие по умолчанию используется для Gzip, если клиент поддерживает сжатие Gzip.

При добавлении поставщика сжатия другие поставщики не добавляются. Например, если поставщик сжатия Gzip является единственным явно добавленным, другие поставщики сжатия не будут добавлены.

Note

По ссылкам в документации на справочные материалы по .NET обычно загружается основная ветвь репозитория, которая представляет направление текущей разработки, предназначенное для следующего релиза .NET. Чтобы выбрать тег для конкретного выпуска, используйте раскрывающееся меню Переключение ветвей или тегов. Дополнительные сведения см. в статье Выбор тега версии исходного кода ASP.NET Core (dotnet/AspNetCore.Docs #26205).

Следующий код:

  • Включает сжатие ответов для 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 . Однако этот подход может не производить наиболее эффективное сжатие. Если необходимо максимально эффективное сжатие, настройте промежуточное ПО для сжатия ответов для достижения оптимальных результатов.

Значения, указывающие, подчеркивает ли операция сжатия скорость или размер сжатия, см. в перечислении 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();

Поставщик сжатия Zstandard

Используйте класс ZstandardCompressionProvider для сжатия ответов с использованием RFC 8878: сжатие Zstandard для HTTP.

Задайте качество сжатия с классом ZstandardCompressionProviderOptions . Уровень качества Zstandard варьируется от 1 до 22, где более высокие значения создают лучшее сжатие, но медленнее скорость. В следующем примере задается качество сжатия Zstandard:

builder.Services.Configure<ZstandardCompressionProviderOptions>(options =>
{
    options.CompressionOptions = new ZstandardCompressionOptions
    {
        Quality = 6 // 1 to 22, higher = better compression, slower
    };
});

Настраиваемые поставщики

Создайте пользовательские реализации сжатия с интерфейсом 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. Чтобы выбрать тег для конкретного выпуска, используйте раскрывающееся меню Переключение ветвей или тегов. Дополнительные сведения см. в статье Выбор тега версии исходного кода 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" в файл ResponseCompressionBody.cs автоматически при сжатии ответа.

Note

По ссылкам в документации на справочные материалы по .NET обычно загружается основная ветвь репозитория, которая представляет направление текущей разработки, предназначенное для следующего релиза .NET. Чтобы выбрать тег для конкретного выпуска, используйте раскрывающееся меню Переключение ветвей или тегов. Дополнительные сведения см. в статье Выбор тега версии исходного кода ASP.NET Core (dotnet/AspNetCore.Docs #26205).

Проблемы с обратным прокси-сервером Nginx

Когда Nginx проксирует запрос, заголовок Accept-Encoding удаляется. Удаление заголовка Accept-Encoding предотвращает промежуточное ПО сжатия от обработки и сжатия ответа. Дополнительные сведения см. в разделе Nginx: Сжатие и декомпрессия. Эта проблема отслеживается в GitHub в задаче dotnet/aspnetcore #5989 - Разработать сквозное сжатие для Nginx.

Отключение динамического сжатия IIS

Чтобы отключить модуль динамического сжатия IIS, настроенный на уровне сервера, см. раздел "Отключение модулей IIS".

Устранение неполадок с сжатием ответов

Используйте средство, например Firefox Browser — версия для разработчиков, которое позволяет задать Accept-Encoding заголовок запроса и изучать заголовки ответов, размер и содержимое. По умолчанию ПО промежуточного слоя сжатия ответов сжимает ответы, соответствующие следующим условиям:

  • Заголовок Accept-Encoding присутствует со значением br, gzip, * (звездочка) или пользовательской кодировкой, которая соответствует индивидуальному поставщику сжатия. Значение не должно быть identity (без кодировки) или иметь значение качества (qvalue, q) значение 0 (ноль).
  • Заголовок Accept-Encoding присутствует со значением br, gzip, zstd* (звездочка) или пользовательской кодировкой, которая соответствует пользовательскому поставщику сжатия. Значение не должно быть identity (без кодировки) или иметь значение качества (qvalue, q) значение 0 (ноль).
  • Тип MIME (Content-Type) должен быть задан и должен соответствовать типу MIME, настроенного ResponseCompressionOptions в классе.

  • Запрос не должен включать заголовок Content-Range.

  • Запрос должен использовать небезопасный протокол гипертекстов (http), если в параметрах промежуточного слоя сжатия ответа не настроен безопасный протокол гипертекста (https).

    Important

    Ознакомьтесь с рисками, связанными с включением безопасного сжатия содержимого, как описано в разделе "Сжатие с помощью HTTPS " ранее в этой статье.

Просмотрите развернутый пример 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();

Пропускная способность сети — это ограниченный ресурс. Уменьшение размера ответа обычно увеличивает скорость реагирования приложения, часто резко. Одним из способов уменьшения размера полезных данных является сжатие ответов приложения.

Просмотреть или скачать образец кода (описание загрузки)

Когда использовать промежуточное ПО для сжатия ответов

Используйте серверные технологии сжатия ответов в IIS, Apache или Nginx. Производительность промежуточного слоя, возможно, не будет такой же, как у модулей сервера. сервер HTTP.sys и Kestrel сервер в настоящее время не предоставляют встроенную поддержку сжатия.

Используйте промежуточное ПО для сжатия ответов, если вы:

Сжатие ответов

Как правило, любой ответ, не являющийся изначально сжатым, может выиграть от сжатия ответа. Ответы, не сжатые в собственном коде, обычно включают: CSS, JavaScript, HTML, XML и JSON. Не следует сжимать изначально сжатые файлы, такие как PNG-файлы. Если вы пытаетесь дополнительно сжать исходный сжатый ответ, любое небольшое дополнительное уменьшение размера и времени передачи, скорее всего, будет нивелировано временем, затраченным на обработку сжатия. Не сжимайте файлы меньше 150–1000 байт (в зависимости от содержимого файла и эффективности сжатия). Затраты на сжатие небольших файлов могут привести к тому, что сжатый файл окажется более крупным, чем несжатый файл.

Когда клиент может обрабатывать сжатое содержимое, клиент должен сообщить серверу о своих возможностях, отправив Accept-Encoding заголовок с запросом. Когда сервер отправляет сжатое содержимое, он должен содержать сведения в заголовке Content-Encoding о кодировании сжатого ответа. Обозначения кодировки содержимого, поддерживаемые ПО промежуточного слоя, показаны в следующей таблице.

Значения заголовков Accept-Encoding Поддерживаемое ПО промежуточного слоя Description
br Да (по умолчанию) Формат сжатых данных Brotli
deflate No Формат сжатых данных Deflate
exi No Эффективный обмен XML W3C
gzip Yes Формат файлов gzip
identity Yes Идентификатор "Нет кодирования": ответ не должен быть закодирован.
pack200-gzip No Формат сетевой передачи для архивов Java
* Yes Любая доступная кодировка содержимого не запрашивается явным образом

Дополнительные сведения см. в Официальном списке кодов содержимого IANA.

ПО промежуточного слоя позволяет добавлять дополнительные поставщики сжатия для пользовательских Accept-Encoding значений заголовков. Дополнительные сведения см. в разделе ниже «Настраиваемые поставщики».

ПО промежуточного слоя может реагировать на значение качества (qvalue q) веса при отправке клиентом для определения приоритетов методов сжатия. Дополнительные сведения см. в статье RFC 9110: Accept-Encoding.

Алгоритмы сжатия подвергаются компромиссу между скоростью сжатия и эффективностью сжатия. Эффективность в этом контексте относится к размеру выходных данных после сжатия. Наименьший размер достигается наиболее оптимальным сжатием.

Заголовки, связанные с запросом, отправкой, кэшированием и получением сжатого содержимого, описаны в таблице ниже.

Header 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 по умолчанию для сжатия.

Configuration

В следующем коде показано, как включить ПО промежуточного слоя сжатия ответов для типов MIME по умолчанию и поставщиков сжатия (Brotli и Gzip):

public class Startup
{
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddResponseCompression();
    }

    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
        app.UseResponseCompression();
    }
}

Notes:

  • app.UseResponseCompression необходимо вызвать перед любым промежуточным ПО, сжимающим ответы. Дополнительные сведения см. в разделе ASP.NET Core ПО промежуточного слоя.
  • Используйте средство, например Fiddler, Firefox Browser Developer, чтобы задать заголовок Accept-Encoding запроса и изучить заголовки ответа, их размеры и содержимое.

Отправьте запрос в пример приложения без заголовка Accept-Encoding и обратите внимание, что ответ не сжат. Заголовки Content-Encoding и Vary отсутствуют в ответе.

Окно Fiddler с результатом запроса без заголовка Accept-Encoding. Ответ не сжимается.

Отправьте запрос в пример приложения с заголовком Accept-Encoding: br (сжатие Brotli) и обратите внимание, что ответ сжимается. На ответе присутствуют заголовки Content-Encoding и Vary.

Окно Fiddler, показывающее результат запроса с заголовком Accept-Encoding и значением br. В ответ добавляются заголовки Vary и content-encoding, и ответ сжимается.

Providers

Поставщик сжатия Brotli

Используйте BrotliCompressionProvider для сжатия ответов с помощью формата сжатия данных Brotli.

Если в 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.Fastest), который может не производить наиболее эффективное сжатие. Если необходимо максимально эффективное сжатие, настройте ПО промежуточного слоя для оптимального сжатия.

Уровень сжатия Description
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.Fastest), который может не производить наиболее эффективное сжатие. Если необходимо максимально эффективное сжатие, настройте ПО промежуточного слоя для оптимального сжатия.

Уровень сжатия Description
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. Однако в примере показано, где будет реализован такой алгоритм сжатия.

Окно Fiddler, демонстрирующее результат запроса с заголовком

Типы MIME

ПО промежуточного слоя задает набор типов MIME по умолчанию для сжатия:

  • application/javascript
  • application/json
  • application/xml
  • text/css
  • text/html
  • text/json
  • text/plain
  • text/xml

Замените или добавьте типы MIME в параметрах ПО промежуточного слоя сжатия ответов. Обратите внимание, что типы MIME с подстановочными знаками, такие как text/* не поддерживаются. Пример приложения добавляет тип MIME для image/svg+xml и сжимает и отправляет изображение баннера 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: Сжатие и декомпрессия. Эта проблема отслеживается путем определения сквозного сжатия для Nginx (dotnet/aspnetcore#5989).

Работа с динамическим сжатием IIS

Если у вас есть активный модуль динамического сжатия IIS, настроенный на уровне сервера, который вы хотите отключить для приложения, отключите модуль с добавлением к файлу web.config . Дополнительные сведения см. в разделе Отключение модулей IIS.

Troubleshooting

Используйте средство, например Fiddler или Firefox Browser Developer, которое позволяет задавать Accept-Encoding заголовок запроса и изучать заголовки ответа, размер и текст. По умолчанию ПО промежуточного слоя сжатия ответов сжимает ответы, соответствующие следующим условиям:

  • Заголовок Accept-Encoding присутствует со значением br, gzip, * или пользовательской кодировкой, которая соответствует вашему настроенному провайдеру пользовательского сжатия. Значение не должно быть identity или иметь значение качества (qvalue, q) значение 0 (ноль).
  • Тип MIME (Content-Type) должен быть задан и должен соответствовать типу MIME, настроенному на ResponseCompressionOptions.
  • Запрос не должен включать Content-Range заголовок.
  • Запрос должен использовать небезопасный протокол (http), если в параметрах промежуточного слоя сжатия ответа не настроен безопасный протокол (https). Обратите внимание на опасность , описанную выше при включении безопасного сжатия содержимого.

Дополнительные ресурсы