dotnet core 不自动从 https 到 http 的 302 重定向
本文记录一个已知问题,或者准确来说是设计如此的行为,在 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
博客园博客只做备份,博客发布就不再更新,如果想看最新博客,请访问 https://blog.lindexi.com/
如图片看不见,请在浏览器开启不安全http内容兼容
![知识共享许可协议](https://licensebuttons.net/l/by-nc-sa/4.0/88x31.png)
本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。欢迎转载、使用、重新发布,但务必保留文章署名[林德熙](https://www.cnblogs.com/lindexi)(包含链接:https://www.cnblogs.com/lindexi ),不得用于商业目的,基于本文修改后的作品务必以相同的许可发布。如有任何疑问,请与我[联系](mailto:lindexi_gd@163.com)。