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 在这里提供的帮助。