ASP.NET Core 中的响应压缩
网络带宽是一种有限资源。 减小响应大小通常可显著提高应用的响应速度。 减小有效负载大小的一种方式是压缩应用的响应。
使用 HTTPS 进行压缩
可以通过 EnableForHttps 选项控制安全连接上的压缩响应,该选项由于安全风险,默认处于禁用状态。 对动态生成的页面使用压缩可能会向 CRIME 和 BREACH 攻击公开该应用。 CRIME 和 BREACH 攻击可以通过防伪造令牌在 ASP.NET Core 中得到缓解。 有关详细信息,请参阅在 ASP.NET Core 中预防跨网站请求伪造 (XSRF/CSRF) 攻击。 有关缓解 BREACH 攻击的信息,请参阅在http://www.breachattack.com/缓解
即使已在应用中禁用 EnableForHttps
,IIS、IIS Express 和 Azure 应用服务也可在 IIS Web 服务器上应用 gzip。 查看响应标头时,请记下“服务器”值。 意外的content-encoding
响应标头值可能是 Web 服务器的结果,而不是 ASP.NET Core 应用配置的结果。
何时使用响应压缩中间件
在 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 |
否 | Java 存档的网络传输格式 |
* |
是 | 任何未显式请求的可用内容编码 |
有关详细信息,请参阅 IANA 官方内容编码列表。
通过响应压缩中间件,可为自定义 Accept-Encoding
标头值添加其他压缩提供程序。 有关详细信息,请参阅下文的自定义提供程序。
由客户端发送时,响应压缩中间件能够对质量值 (qvalue, q
) 权重做出反应,以设置压缩方案的优先级。 有关详细信息,请参阅 RFC 9110: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();
注释:
- 将
EnableForHttps
设置为true
会形成安全隐患。 有关详细信息,请参阅本文中的使用 HTTPS 进行压缩。 - 必须在任何压缩响应的中间件之前调用
app.UseResponseCompression
。 有关详细信息,请参阅 ASP.NET Core 中间件。 - 使用 Firefox Browser Developer 等工具设置
Accept-Encoding
请求头,并检查响应头、大小和正文。
向示例应用提交不带 Accept-Encoding
标头的请求,并观察响应是否未压缩。 标头 Content-Encoding
不在响应标头集合中。
例如,在 Firefox 开发人员中:
- 选择“网络”选项卡。
- 右键单击“网络请求”列表中的请求,然后选择“编辑并重新发送”
- 将
Accept-Encoding:
从gzip, deflate, br
更改为none
。 - 选择“发送”。
使用开发人员工具向包含浏览器的示例应用提交请求,并观察响应是否被压缩。 响应中存在 Content-Encoding
和 Vary
标头。
提供程序
Brotli 和 Gzip 压缩提供程序
使用 BrotliCompressionProvider 以 Brotli 压缩数据格式压缩响应。
如果没有将压缩提供程序显式添加到 CompressionProviderCollection:
- 默认情况下,Brotli 压缩提供程序与 Gzip 压缩提供程序会一起添加到压缩提供程序数组中。
- 当客户端支持 Brotli 压缩数据格式时,压缩默认为 Brotli 压缩。 如果客户端不支持 Brotli,则当客户端支持 Gzip 压缩时,压缩默认为 Gzip。
注意
指向 .NET 参考源的文档链接通常会加载存储库的默认分支,该分支表示针对下一个 .NET 版本的当前开发。 若要为特定版本选择标记,请使用“切换分支或标记”下拉列表。 有关详细信息,请参阅如何选择 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),这可能不会产生最高效的压缩。 如果需要最高效的压缩,请配置响应压缩中间件以实现最佳压缩。
请参阅压缩枚举值,该值用来指示压缩操作是强调速度还是强调压缩大小。
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 版本的当前开发。 若要为特定版本选择标记,请使用“切换分支或标记”下拉列表。 有关详细信息,请参阅如何选择 ASP.NET Core 源代码的版本标记 (dotnet/AspNetCore.Docs #26205)。
使用 ResponseCompressionOptions.MimeTypes
替换或添加 MIME 类型。 请注意,不支持通配符 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
标头。
注意
指向 .NET 参考源的文档链接通常会加载存储库的默认分支,该分支表示针对下一个 .NET 版本的当前开发。 若要为特定版本选择标记,请使用“切换分支或标记”下拉列表。 有关详细信息,请参阅如何选择 ASP.NET Core 源代码的版本标记 (dotnet/AspNetCore.Docs #26205)。
在 Nginx 反向代理后面时出现的中间件问题
当 Nginx 代理请求时,将删除 Accept-Encoding
标头。 删除 Accept-Encoding
标头会阻止响应压缩中间件压缩响应。 有关详细信息,请参阅 NGINX:压缩和解压缩。 此问题由找出 Nginx 的直通压缩 (dotnet/aspnetcore#5989) 跟踪。
禁用 IIS 动态压缩
若要禁用在服务器级别配置的 IIS 动态压缩模块,请参阅 禁用 IIS 模块。
排查响应压缩问题
使用 Firefox Browser Developer 等工具,可借助这些工具设置 Accept-Encoding
请求头,并研究响应头、大小和正文。 默认情况下,响应压缩中间件压缩满足以下条件的响应:
Accept-Encoding
标头存在,且值为br
、gzip
、*
或与已建立的自定义压缩提供程序匹配的自定义编码。 该值不得为identity
,或将质量值 (qvalue,q
) 设置为 0(零)。- 必须设置 MIME 类型 (
Content-Type
),并且该类型必须与在 ResponseCompressionOptions 上配置的 MIME 类型匹配。 - 请求不得包含
Content-Range
标头。 - 请求必须使用不安全协议 (http),除非在“响应压缩中间件”选项中配置了安全协议 (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();
其他资源
注意
指向 .NET 参考源的文档链接通常会加载存储库的默认分支,该分支表示针对下一个 .NET 版本的当前开发。 若要为特定版本选择标记,请使用“切换分支或标记”下拉列表。 有关详细信息,请参阅如何选择 ASP.NET Core 源代码的版本标记 (dotnet/AspNetCore.Docs #26205)。
网络带宽是一种有限资源。 减小响应大小通常可显著提高应用的响应速度。 减小有效负载大小的一种方式是压缩应用的响应。
何时使用响应压缩中间件
在 IIS、Apache 或 Nginx 中使用基于服务器的响应压缩技术。 中间件的性能可能与服务器模块的性能不匹配。 HTTP.sys 服务器和 Kestrel 服务器当前不提供内置压缩支持。
在以下情况下使用响应压缩中间件:
- 无法使用以下基于服务器的压缩技术:
- 直接托管在以下位置上:
- HTTP.sys 服务器(以前称为 WebListener)
- Kestrel server
响应压缩
通常,任何未本机压缩的响应都可以从响应压缩中获益。 未本机压缩的响应通常包括: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 |
否 | Java 存档的网络传输格式 |
* |
是 | 任何未显式请求的可用内容编码 |
有关详细信息,请参阅 IANA 官方内容编码列表。
通过中间件,可为自定义 Accept-Encoding
标头值添加其他压缩提供程序。 有关详细信息,请参阅下面的自定义提供程序。
由客户端发送时,中间件能够对质量值 (qvalue, q
) 权重做出反应,以设置压缩方案的优先级。 有关详细信息,请参阅 RFC 9110: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 类型和压缩提供程序(Brotli 和 Gzip)启用响应压缩中间件:
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddResponseCompression();
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
app.UseResponseCompression();
}
}
注意:
app.UseResponseCompression
必须在任何压缩响应的中间件之前调用。 有关详细信息,请参阅 ASP.NET Core 中间件。- 使用 Fiddler、Firefox Browser Developer 等工具设置
Accept-Encoding
请求头,并研究响应头、大小和正文。
向示例应用提交不带 Accept-Encoding
标头的请求,并观察响应是否未压缩。 响应中不存在 Content-Encoding
和 Vary
标头。
向示例应用提交带 Accept-Encoding: br
标头(Brotli 压缩)的请求,并观察响应是否已压缩。 响应中存在 Content-Encoding
和 Vary
标头。
提供程序
Brotli 压缩提供程序
使用 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),这可能不会产生最有效的压缩。 如果需要最高效的压缩,请配置中间件以实现最佳压缩。
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.Fastest),这可能不会产生最有效的压缩。 如果需要最高效的压缩,请配置中间件以实现最佳压缩。
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
标头的请求,并观察响应头。 响应中存在 Vary
和 Content-Encoding
标头。 示例未压缩响应正文(未显示)。 示例的 CustomCompressionProvider
类中没有压缩实现。 但是,该示例演示了在何处实现此类压缩算法。
MIME 类型
中间件为压缩指定一组默认的 MIME 类型:
application/javascript
application/json
application/xml
text/css
text/html
text/json
text/plain
text/xml
使用“响应压缩中间件”选项替换或追加 MIME 类型。 请注意,不支持通配符 MIME 类型,如 text/*
。 示例应用为 image/svg+xml
添加 MIME 类型,并压缩和提供 ASP.NET Core 横幅图像 (banner.svg)。
public void ConfigureServices(IServiceCollection services)
{
services.AddResponseCompression(options =>
{
options.Providers.Add<BrotliCompressionProvider>();
options.Providers.Add<GzipCompressionProvider>();
options.Providers.Add<CustomCompressionProvider>();
options.MimeTypes =
ResponseCompressionDefaults.MimeTypes.Concat(
new[] { "image/svg+xml" });
});
}
使用安全协议进行压缩
可以通过 EnableForHttps
选项控制安全连接上的压缩响应,该选项默认处于禁用状态。 对动态生成的页面使用压缩可能会导致安全问题,例如 CRIME 和 BREACH 攻击。
添加 Vary 标头
在基于 Accept-Encoding
标头压缩响应时,可能有多个压缩版本的响应和一个未压缩版本。 为了向客户端和代理缓存指示存在多个版本并且应存储这些版本,向 Vary
标头添加了 Accept-Encoding
值。 在 ASP.NET Core 2.0 或更高版本中,中间件在压缩响应时自动添加了 Vary
标头。
在 Nginx 反向代理后面时出现的中间件问题
当 Nginx 代理请求时,将删除 Accept-Encoding
标头。 删除 Accept-Encoding
标头会阻止中间件压缩响应。 有关详细信息,请参阅 NGINX:压缩和解压缩。 此问题由找出 Nginx 的直通压缩 (dotnet/aspnetcore#5989) 跟踪。
使用 IIS 动态压缩
如果在服务器级别配置了一个活动的 IIS 动态压缩模块,并希望为应用禁用该模块,请禁用该模块加上 web.config 文件。 有关详细信息,请参阅禁用 IIS 模块。
疑难解答
使用 Fiddler、Firefox Browser Developer 等工具,可借助这些工具设置 Accept-Encoding
请求头,并研究响应头、大小和正文。 默认情况下,响应压缩中间件压缩满足以下条件的响应:
Accept-Encoding
标头存在,且值为br
、gzip
、*
或与已建立的自定义压缩提供程序匹配的自定义编码。 该值不得为identity
,或将质量值 (qvalue,q
) 设置为 0(零)。- 必须设置 MIME 类型 (
Content-Type
),并且该类型必须与在 ResponseCompressionOptions 上配置的 MIME 类型匹配。 - 请求不得包含
Content-Range
标头。 - 请求必须使用不安全协议 (http),除非在“响应压缩中间件”选项中配置了安全协议 (https)。 启用安全内容压缩时,请注意上述危险。