C# HttpClient 不处理 304/307 重定向
C# HttpClient not handling 304/307 redirects
我正在尝试让 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: The I/O operation has been aborted because of either a thread exit or an application request.
此请求在 Postman 上完全正常,我已经尝试过 https 和 http 但没有成功。当访问该站点并使用 Chrome 的开发工具时,如果您使用 http 而不是 https,它会 returns 一个 307 并将您重定向到 https 站点,然后 returns a 304。我不明白为什么 HttpClient 只是超时而不是给出有用的响应。
有什么方法可以让它工作吗?我错过了一些简单的东西吗?
更新 - 2021-01-29
我已经在多个不同的 .NET 版本上进行了尝试,发现这可能是 HttpClient 的错误,因为此代码适用于 .NET Core 2.0 但不适用于 .NET Core 2.1。
测试版本
- .NET Framework 4.8:有效
- .NET 核心 1.0:有效
- .NET 核心 1.1:有效
- .NET 核心 2.0:有效
- .NET Core 2.1:不起作用
- .NET Core 2.2:不起作用
- .NET Core 3.0:不工作
- .NET Core 3.1:不工作
- .NET 5:不起作用
事实证明这根本不是 .NET 问题。我在 GitHub 上提出了 this 问题,因为所有证据都指向 .NET Core 2.1 之后的 HttpClientHandler 中断。 Stephen 能够向我指出,在 .NET Core 2.1 之前,HttpClient 默认设置 Connection: Keep-Alive
header。
我一直在测试的罪魁祸首 URL 似乎需要以下条件之一才能工作:
- 一个
Connection: Keep-Alive
header
Accept: */*
header,或更具体的请求内容
- 要使用 HTTP/2 协议发送的请求。
作为参考,要应用 Header 修复之一,请使用 httpClient.DefaultRequestHeaders.Add(string, string)
, and to set the HTTP protocol, use httpClient.DefaultRequestVersion = HttpVersion.Version20;
这个问题原来不是 C# 的直接问题,而是在 .NET Core 2.1 之后发送的默认 headers 发生了变化。如果禁用所有 header(包括 Postman 令牌 header),我发现该问题可在 Postman 上重现。
我正在尝试让 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: The I/O operation has been aborted because of either a thread exit or an application request.
此请求在 Postman 上完全正常,我已经尝试过 https 和 http 但没有成功。当访问该站点并使用 Chrome 的开发工具时,如果您使用 http 而不是 https,它会 returns 一个 307 并将您重定向到 https 站点,然后 returns a 304。我不明白为什么 HttpClient 只是超时而不是给出有用的响应。
有什么方法可以让它工作吗?我错过了一些简单的东西吗?
更新 - 2021-01-29
我已经在多个不同的 .NET 版本上进行了尝试,发现这可能是 HttpClient 的错误,因为此代码适用于 .NET Core 2.0 但不适用于 .NET Core 2.1。
测试版本
- .NET Framework 4.8:有效
- .NET 核心 1.0:有效
- .NET 核心 1.1:有效
- .NET 核心 2.0:有效
- .NET Core 2.1:不起作用
- .NET Core 2.2:不起作用
- .NET Core 3.0:不工作
- .NET Core 3.1:不工作
- .NET 5:不起作用
事实证明这根本不是 .NET 问题。我在 GitHub 上提出了 this 问题,因为所有证据都指向 .NET Core 2.1 之后的 HttpClientHandler 中断。 Stephen 能够向我指出,在 .NET Core 2.1 之前,HttpClient 默认设置 Connection: Keep-Alive
header。
我一直在测试的罪魁祸首 URL 似乎需要以下条件之一才能工作:
- 一个
Connection: Keep-Alive
header Accept: */*
header,或更具体的请求内容- 要使用 HTTP/2 协议发送的请求。
作为参考,要应用 Header 修复之一,请使用 httpClient.DefaultRequestHeaders.Add(string, string)
, and to set the HTTP protocol, use httpClient.DefaultRequestVersion = HttpVersion.Version20;
这个问题原来不是 C# 的直接问题,而是在 .NET Core 2.1 之后发送的默认 headers 发生了变化。如果禁用所有 header(包括 Postman 令牌 header),我发现该问题可在 Postman 上重现。