Web API 发送压缩响应的问题
Web API issue with sending compressed response
我一直致力于让 gzip/deflate 压缩在 Web API 响应上工作。我一直在使用 Github - MessageHandlers.Compression 中的代码。但是它似乎没有用。 Content-Encoding header 没有出现在 Google 开发人员控制台或 Firefox 的 Firebug 中,并且 Content-Length 始终设置为未压缩的数据大小。所以我一直在剥离代码,直到我得到以下结果:
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
// Send the request to the web api controller
var response = await base.SendAsync(request, cancellationToken).ConfigureAwait(false);
// Compress uncompressed responses from the server
if (response.Content != null && request.Headers.AcceptEncoding.IsNotNullOrEmpty())
{
var content = response.Content;
var bytes = content.ReadAsByteArrayAsync().Result;
if (bytes != null && bytes.Length > 1024)
{
// The data has already been serialised to JSon by this point
var compressedBytes = Compress(bytes);
response.Content = new ByteArrayContent(compressedBytes);
var headers = response.Content.Headers;
headers.Remove("Content-Type");
headers.ContentLength = compressedBytes.Length;
headers.ContentEncoding.Clear();
headers.ContentEncoding.Add("gzip");
headers.Add("Content-Type", "application/json");
}
}
return response;
}
private static byte[] Compress(byte[] input)
{
using (var compressStream = new MemoryStream())
{
using (var compressor = new GZipStream(compressStream, CompressionMode.Compress))
{
compressor.Write(input, 0, input.Length);
compressor.Close();
return compressStream.ToArray();
}
}
}
我最初这样做时犯了一个错误,当我在 Compress 方法中使用 DeflateStream 时,将 header 中的内容编码设置为 'gzip'。正如您所期望的那样,我在浏览器中遇到了一个错误,但是响应 header 是正确的(!)。也就是说,设置了 Content-Encoding header 并且 Content-Length 是正确的。同样,查看原始数据我可以清楚地看到是否被压缩了。尽管我纠正了错误,但问题又回来了。
我想知道的是最新版本的浏览器会在后台解压缩内容,还是我的代码确实有问题?响应以 Json 格式发送
非常感谢任何帮助。
编辑
我尝试使用 Global.asax 中的以下方法将 header 转储到日志文件(按照它们在日志中出现的顺序列出):
Application_PreSendRequestHeaders
Application_EndRequest
Application_PreSendRequestContent
在每种情况下,所需的 header 都在那里,即使它们没有出现在 Google 开发人员控制台中。然后我查看了 Code Project 上的解决方案。当从命令行 运行 时,一切都按预期工作。但是,当我从 Google Chrome 调用 Web 服务器时,我得到了完全相同的结果。也就是说,没有 Content-Encoding header,也没有关于内容是否被压缩的指示。然而,随着开发人员控制台的打开,很容易在其他站点看到这个 header(例如堆栈溢出)。因此,我不得不假设这与 Web api 服务的压缩响应有关。很难知道这是否真的在客户端工作。
如果有人不想阅读所有评论,答案来自 Jerry Hewett (jerhewet)。也就是说,防病毒软件会在响应到达浏览器之前将其拦截。防病毒软件解压缩数据,无疑是扫描过程的一部分。非常感谢 Jerry 在这里提供的帮助。
我一直致力于让 gzip/deflate 压缩在 Web API 响应上工作。我一直在使用 Github - MessageHandlers.Compression 中的代码。但是它似乎没有用。 Content-Encoding header 没有出现在 Google 开发人员控制台或 Firefox 的 Firebug 中,并且 Content-Length 始终设置为未压缩的数据大小。所以我一直在剥离代码,直到我得到以下结果:
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
// Send the request to the web api controller
var response = await base.SendAsync(request, cancellationToken).ConfigureAwait(false);
// Compress uncompressed responses from the server
if (response.Content != null && request.Headers.AcceptEncoding.IsNotNullOrEmpty())
{
var content = response.Content;
var bytes = content.ReadAsByteArrayAsync().Result;
if (bytes != null && bytes.Length > 1024)
{
// The data has already been serialised to JSon by this point
var compressedBytes = Compress(bytes);
response.Content = new ByteArrayContent(compressedBytes);
var headers = response.Content.Headers;
headers.Remove("Content-Type");
headers.ContentLength = compressedBytes.Length;
headers.ContentEncoding.Clear();
headers.ContentEncoding.Add("gzip");
headers.Add("Content-Type", "application/json");
}
}
return response;
}
private static byte[] Compress(byte[] input)
{
using (var compressStream = new MemoryStream())
{
using (var compressor = new GZipStream(compressStream, CompressionMode.Compress))
{
compressor.Write(input, 0, input.Length);
compressor.Close();
return compressStream.ToArray();
}
}
}
我最初这样做时犯了一个错误,当我在 Compress 方法中使用 DeflateStream 时,将 header 中的内容编码设置为 'gzip'。正如您所期望的那样,我在浏览器中遇到了一个错误,但是响应 header 是正确的(!)。也就是说,设置了 Content-Encoding header 并且 Content-Length 是正确的。同样,查看原始数据我可以清楚地看到是否被压缩了。尽管我纠正了错误,但问题又回来了。
我想知道的是最新版本的浏览器会在后台解压缩内容,还是我的代码确实有问题?响应以 Json 格式发送
非常感谢任何帮助。
编辑
我尝试使用 Global.asax 中的以下方法将 header 转储到日志文件(按照它们在日志中出现的顺序列出):
Application_PreSendRequestHeaders
Application_EndRequest
Application_PreSendRequestContent
在每种情况下,所需的 header 都在那里,即使它们没有出现在 Google 开发人员控制台中。然后我查看了 Code Project 上的解决方案。当从命令行 运行 时,一切都按预期工作。但是,当我从 Google Chrome 调用 Web 服务器时,我得到了完全相同的结果。也就是说,没有 Content-Encoding header,也没有关于内容是否被压缩的指示。然而,随着开发人员控制台的打开,很容易在其他站点看到这个 header(例如堆栈溢出)。因此,我不得不假设这与 Web api 服务的压缩响应有关。很难知道这是否真的在客户端工作。
如果有人不想阅读所有评论,答案来自 Jerry Hewett (jerhewet)。也就是说,防病毒软件会在响应到达浏览器之前将其拦截。防病毒软件解压缩数据,无疑是扫描过程的一部分。非常感谢 Jerry 在这里提供的帮助。