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

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

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

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

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

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

Используйте серверные технологии сжатия ответов в 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 "Подстановочный знак" — любая доступная кодировка содержимого не запрашивается явно Устранение неполадок с сжатием ответов

Дополнительные сведения см. в списке кодирования официального содержимого 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 по умолчанию для сжатия.
  • Как добавить настраиваемого поставщика сжатия ответов.

Настройка middleware для сжатия ответов

В следующем коде показано, как включить ПО промежуточного слоя сжатия ответа для типов 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:

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

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

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

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

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

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

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

  • По умолчанию поставщики сжатия Brotli и Gzip добавляются в массив поставщиков сжатия.
  • Когда клиент поддерживает формат сжатых данных Brotli, по умолчанию используется сжатие Brotli.
  • Если клиент не поддерживает 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();

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

Создайте пользовательские реализации сжатия с интерфейсом 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 (ноль).

  • Тип 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). Обратите внимание на опасность , описанную выше при включении безопасного сжатия содержимого.

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