C# HttpClient 不处理 304/307 重定向

Ste*_*ood 5 c# http-redirect dotnet-httpclient .net-core .net-5

我正在尝试让 HttpClient 从网站中提取网站图标,并且在 99% 的情况下,此代码可以按预期工作:

var httpClient = new HttpClient();
httpClient.Timeout = TimeSpan.FromSeconds(10);

var response = await httpClient.GetAsync("https://www.tesco.com/favicon.ico");
response.EnsureSuccessStatusCode();
Run Code Online (Sandbox Code Playgroud)

我在几个网站上发现我的 GetAsync 方法只是超时,我相信这与其重定向有关。如果在控制台应用程序中运行上述代码,10 秒后会在 TaskCanceledException 和 IOException 中引发以下异常:

SocketException:由于线程退出或应用程序请求,I/O 操作已中止。

这个请求在 Postman 上完全正常,我尝试过 https 和 http 但没有成功。当访问该网站并使用 Chrome 的开发工具时,看起来如果您使用 http 而不是 https,它会返回 307 并将您重定向到 https 网站,然后返回 304。我不明白为什么 HttpClient 只是计时而不是给出有用的回应。

有什么办法让它发挥作用吗?我错过了一些简单的事情吗?

更新 - 2021-01-29

我在多个不同的 .NET 版本上进行了尝试,发现这可能是 HttpClient 的一个错误,因为此代码适用于 .NET Core 2.0,但不适用于 .NET Core 2.1。

已测试版本

  • .NET Framework 4.8:有效
  • .NET Core 1.0:有效
  • .NET Core 1.1:有效
  • .NET Core 2.0:有效
  • .NET Core 2.1:不起作用
  • .NET Core 2.2:不起作用
  • .NET Core 3.0:不起作用
  • .NET Core 3.1:不起作用
  • .NET 5:不起作用

Ste*_*ood 4

事实证明这根本不是 .NET 问题。我在 GitHub 上提出了这个问题,因为所有证据都表明 HttpClientHandler 在 .NET Core 2.1 之后出现问题。Stephen 向我指出,在 .NET Core 2.1 之前,Connection: Keep-AliveHttpClient 中默认设置了标头。

我一直在测试的罪魁祸首 URL 似乎需要以下其中一项才能工作:

  • 一个Connection: Keep-Alive标题
  • Accept: */*头,或者更具体的请求内容
  • 使用 HTTP/2 协议发送的请求。

作为参考,要应用标头修复之一,请使用httpClient.DefaultRequestHeaders.Add(string, string),要设置 HTTP 协议,请使用httpClient.DefaultRequestVersion = HttpVersion.Version20;

事实证明,此问题不是 C# 的直接问题,而是在 .NET Core 2.1 之后发送的默认标头发生了更改。我发现如果禁用所有标头(包括 Postman 令牌标头),该问题可以在 Postman 上重现。