【问题标题】:HttpClient not sending Accept-Encoding on Windows 2008 R2HttpClient 未在 Windows 2008 R2 上发送 Accept-Encoding
【发布时间】:2018-02-09 09:56:56
【问题描述】:

我有一个执行 GET 请求的 .NET Core 2.0 控制台应用程序。

似乎已发布的版本没有在测试机器上发送Accept-Encoding 标头进行压缩,但在我的本地机器上工作。

我找不到任何其他会使压缩失败的前置请求。两者都运行 .NET Core 2.1.4 SDK。

我已经通过在两种环境中运行 dotnet Console.dll 测试了控制台应用程序。

  1. 在 VS2017 中发布
  2. 转到输出文件夹并运行dotnet Console.dll。验证 Fiddler 中是否存在标头。
  3. 复制整个输出文件夹并部署到服务器上
  4. 再次运行 dotnet Console.dll 并使用 Fiddler 验证服务器上缺少的标头。

HttpClientRestSharp 我都试过了,我很困惑。

转到响应请求标头的页面的概念证明:

 var handler = new HttpClientHandler()
            {
                AutomaticDecompression = DecompressionMethods.Deflate | DecompressionMethods.GZip
            };

 using (var client = new HttpClient(handler))
 {
      response = client.GetStringAsync("http://scooterlabs.com/echo").Result;
 }

本地环境(Win10)

GET http://scooterlabs.com/echo HTTP/1.1
Connection: Keep-Alive
Accept-Encoding: gzip, deflate
Host: scooterlabs.com

服务器(AWS 上的 Win2008 R2)

GET http://scooterlabs.com/echo HTTP/1.1
Connection: Keep-Alive
Host: scooterlabs.com

【问题讨论】:

  • 那是请求标头。我不确定 scooterlabs 使用什么。编辑:我尝试使用 WebClient,这似乎在服务器上运行良好,所以 HttpClient 实现中的某些东西似乎不起作用?
  • HttpClient 工作得很好。在您的示例中,您 使用 HttpClient,您使用的是 RestClient。无论如何,如果压缩不起作用,成千上万的开发人员会在 5 年前注意到。
  • 写一个minimal, reproducible的例子,使用Fiddler来检查HTTP请求和响应。如果请求标头存在并且服务压缩响应,则 HttpClient 没有问题
  • 如果你自己添加标题(并删除AutomaticDecompression)呢?
  • @JunWeiLee 换一种说法——我在 Core 2.0 上使用 HttpClient 并且压缩有效。你假设它没有。 服务器 不是 HttpClient。如果标头没有到达服务器,则可能是某些东西(例如防火墙)将其删除。服务器是否首先支持压缩?你是如何配置服务器的?什么服务器?

标签: c# .net .net-core dotnet-httpclient


【解决方案1】:

我最好的猜测是因为 WinHttp 库,默认情况下由 Windows 上的 HttpClient does not support gzip\deflate 在 Windows 8.1+ 之前的 Windows 版本上使用。支持时 - WinHttp 还将设置 Accept-Encoding 标头。因此,在 Windows Server 2008 上,当 .NET 通过 WinHttp 路由请求时 - 它要么设置此选项并被忽略,要么检查是否支持此选项,如果不支持 - 则不设置它。

如果您手动设置此标头(如client.DefaultRequestHeaders.AcceptEncoding.Add(new StringWithQualityHeaderValue("gzip"));) - 选项仍然被忽略,但标头通过并且服务器返回压缩响应。如果支持 - WinHttp 将解压缩该响应并删除 Content-Encoding 标头,因此响应将解压到 .NET。如果不支持 - 如果您设置 AutomaticDecompression,响应将压缩到达,.NET 本身将解压缩它。

所以总结一下 - 在 8.1 之前的 Windows 版本上,您似乎需要同时设置 AutomaticDecompression 和相关的 Accept-Encoding 标头才能按预期工作。

【讨论】:

  • 在 Windows 7 中,如果您手动设置标题(例如:httprequest.Headers.Add(HttpRequestHeader.AcceptEncoding, "gzip, deflate;q=0.8");,并且不指定 AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate;,则流将使用首选方法之一压缩到达(gzip,如果可用,在示例代码中)。System.IO.Compression.GZipStreamSystem.IO.Compression.DeflateStream 可用于解压缩流并将其复制到 MemoryStream 中,用于最终的StreamReader.ReadToEnd([MemoryStream])
【解决方案2】:

根据 Ivan 和 Evk 的回答,这似乎是特定于旧版本 Windows(早于 Win8.1)的问题。以下是在旧版本 Windows 上解决和成功处理压缩的方法。

   var handler = new HttpClientHandler()
                {
                    AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate
                };

   using (var client = new HttpClient(handler))
   {
        client.DefaultRequestHeaders.AcceptEncoding.Add(new StringWithQualityHeaderValue("gzip"));
        client.DefaultRequestHeaders.AcceptEncoding.Add(new StringWithQualityHeaderValue("deflate"));
        response = client.GetStringAsync("http://scooterlabs.com/echo").Result;
   }

AutomaticDecompression 必须在标头之外设置,否则您将获得压缩的有效负载。

【讨论】:

    【解决方案3】:

    不是答案,尽管我尝试在 Azure 的 Win Server 2008 R2 上使用不同的 Echo 服务器 (.NET Core SDK 2.1.4) 重现此问题

    // http://scooterlabs.com/echo output
    
    [headers] => Array
    (
        [Connection] => Keep-Alive
        [Host] => scooterlabs.com
    )
    
    
    // http://httpbin.org/headers output
    {
      "headers": {
        "Connection": "close",
        "Host": "httpbin.org"
      }
    }
    
    // https://postman-echo.com/headers output
    {
        "headers": {
            "host": "postman-echo.com",
            "x-forwarded-port": "443",
            "x-forwarded-proto": "https"
        }
    }
    

    在 Win10 上,我确实也有这些标题。

    // http://scooterlabs.com/echo output
    [headers] => Array
    (
        [Connection] => Keep-Alive
        [Accept-Encoding] => gzip, deflate
        [Host] => scooterlabs.com
    )
    
    // http://httpbin.org/headers output
    {
      "headers": {
        "Accept-Encoding": "gzip, deflate",
        "Connection": "close",
        "Host": "httpbin.org"
      }
    }
    
    // https://postman-echo.com/headers output
    {
        "headers": {
            "host": "postman-echo.com",
            "accept-encoding": "gzip, deflate",
            "x-forwarded-port": "443",
            "x-forwarded-proto": "https"
        }
    }
    

    这让我觉得 HttpClientAccept-Encoding 标头在 WS 2008 R2 上确实不支持。

    【讨论】:

    • 谢谢,刚刚通过 Windows 8.1 VM 确认它确实已设置。结合@Evk 的回答,我们可以得出结论,这可能是核心团队可能想要研究的东西,因为它确实可以处理压缩。
    猜你喜欢
    • 1970-01-01
    • 2012-07-08
    • 2012-09-23
    • 1970-01-01
    • 2011-09-22
    • 2019-11-08
    • 2012-06-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多