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

Posted

技术标签:

【中文标题】C# HttpClient 不处理 304/307 重定向【英文标题】:C# HttpClient not handling 304/307 redirects 【发布时间】:2021-01-27 14:05:39 【问题描述】:

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

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

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

我在几个网站上发现我的 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:不起作用

【问题讨论】:

可能与HttpClientHandler的实现方式有关,因为2.1docs.microsoft.com/en-us/dotnet/api/… 好像是这样。刚刚使用该链接中的第一个示例切换到旧的 http 协议栈,我放置的示例再次返回 200 OK 响应。我会做更多的调查,看看有什么影响。看起来这可能不适用于 .NET 5,但我会尝试一些事情并发布更新。干杯@Hostel 【参考方案1】:

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

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

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

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

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

【讨论】:

以上是关于C# HttpClient 不处理 304/307 重定向的主要内容,如果未能解决你的问题,请参考以下文章

常见http返回的状态码response code含义

C# httpClient 不返回内容

C# HTTPClient 不发送请求

httpclient调用c#中不支持的媒体类型

C# HttpClient 不发送 POST 变量

使用 HttpClient C# .NET 获取 URL