c# - C# HttpClient 不处理 304/307 重定向
问题描述
我正在尝试让 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:不起作用
解决方案
事实证明,这根本不是 .NET 问题。我在 GitHub 上提出了这个问题,因为所有证据都指向 .NET Core 2.1 之后的 HttpClientHandler 中断。Stephen 能够向我指出,在 .NET Core 2.1 之前,Connection: Keep-Alive
HttpClient 中默认设置了一个标头。
我一直在测试的罪魁祸首 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 上重现。
推荐阅读
- ssas - .net 项目中是否有 SSAS 的替代方案
- php - 如何在 laravel 视图刀片中显示来自数据库列的 Json 编码数据
- php - PHP字符串比较问题
- c# - 将数据库服务器移动到 Azure 时,除了连接字符串之外,sql 连接还有哪些变化?
- angular - 使用 Ionic 的低质量 OL 地图
- azure - 如何使用 Azure Active Directory 为外部应用程序设置客户端凭据流
- excel - 如何使用代码在信任中心启用宏设置
- oracle - 如何在 Oracle 和 SQL Server 中的 case 表达式的结果中使用数学表达式
- r - 如何重新排列数据框?
- logstash - 安装 logstash ubuntu 后 /etc/init.d 中缺少 Logstash 文件