Skip to content

dotnet core 不自动从 https 到 http 的 302 重定向

Updated: at 08:22,Created: at 11:36

本文记录一个已知问题,或者准确来说是设计如此的行为,在 dotnet core 下,无论是 dotnet core 3.1 还是 dotnet 5 或 dotnet 6 或 dotnet 7 等,如果访问的 https 链接返回 302 状态码,且跳转的链接是一个 http 链接,那将不会自动跳转

默认情况下,咱可以通过设置 HttpClient 的 HttpClientHandler 从而设置 AllowAutoRedirect 属性,让 HttpClient 自动执行 302 跳转,且可以加上 MaxAutomaticRedirections 设置允许最大的跳转次数

private static HttpClient _httpClient = new HttpClient
(
new HttpClientHandler
{
AllowAutoRedirect = true,
MaxAutomaticRedirections = 2
}
);

对应的,在 dotnet 6 或更高的版本,可以使用 SocketsHttpHandler 代替 HttpClientHandler 类型,代替之后的代码其实也差不多,请看以下代码,更多请看 dotnet 6 HttpClientHandler 和 SocketsHttpHandler 有什么差别

HttpMessageHandler handler = new SocketsHttpHandler()
{
AllowAutoRedirect = true,
MaxAutomaticRedirections = 10,
};
using var httpClient = new HttpClient(handler);

这在大部分情况下都能正常工作,但是如果所访问的链接是一个 https 链接,且此链接返回 302 跳转到一个 http 链接上,那使用 HttpClient 将不会自动跳转,而是返回 302 的状态码,且在 Header 的 Location 上写明了后台返回的 http 链接

这是 dotnet core 的设计如此,可以通过本文的参考看到大佬们的讨论

由于从 https 跳转到 http 在大部分时候来说,都是十分诡异的行为。默认不要让 HttpClient 帮助自动跳转也是十分符合预期的行为

如果自己明确知道没有问题,那就自己加上跳转的代码吧

如以下的例子代码,先判断 StatusCode 是 Redirect 然后拿 Headers.Location 重新访问

var httpResponseMessage = await httpClient.GetAsync(url);
var resultResponseMessage = httpResponseMessage;
if (httpResponseMessage.StatusCode == HttpStatusCode.Redirect)
{
var location = httpResponseMessage.Headers.Location;
if (location is not null)
{
var newResponseMessage = await httpClient.GetAsync(location);
resultResponseMessage = newResponseMessage;
}
else
{
// 理论上不能为空吧,抛个异常还是返回就看你业务
}
}

默认行为禁止 https->http 的跳转,是一个很合理的设计。如果明确知道后台想要如此行为,最好先去将后台的伙伴打一顿,如果打不过,再考虑按照以上代码的方式更改

参考:

HttpClient does not follow 302 redirects · Issue #23801 · dotnet/runtime

HttpClient follow 302 redirects with .NET Core Brian Pedersen’s Sitecore and .NET Blog

Problem with HttpClient after updating my project from net461 to netcoreapp2.0 · Issue #23697 · dotnet/runtime

Response status code does not indicate success: 302 (Moved Temporarily). · Issue #894 · TelegramBots/Telegram.Bot

Change System.Net.Http to throw exception for HTTPS -> HTTP redirects · Issue #23813 · dotnet/runtime

Log when an insecure Https -> Http redirect is blocked by rmkerr · Pull Request #27077 · dotnet/corefx


知识共享许可协议

原文链接: http://blog.lindexi.com/post/dotnet-core-%E4%B8%8D%E8%87%AA%E5%8A%A8%E4%BB%8E-https-%E5%88%B0-http-%E7%9A%84-302-%E9%87%8D%E5%AE%9A%E5%90%91

本作品采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可。 欢迎转载、使用、重新发布,但务必保留文章署名 林德熙 (包含链接: https://blog.lindexi.com ),不得用于商业目的,基于本文修改后的作品务必以相同的许可发布。如有任何疑问,请与我 联系