这个答案关于如何制作的问题HttpClient
不遵循重定向给出了在创建实际客户端时设置的解决方案:
var handler = new HttpClientHandler { AllowAutoRedirect = false };
var client = new HttpClient(handler);
答案下面的评论是我的实际问题:
是否可以根据每个请求执行此操作不需要两个单独的 HttpClient 实例(即一个允许重定向,一个不允许重定向)?
我现在也有一个具体的原因想要单独的客户端:我希望客户端保留早期请求中的 cookie。我试图首先执行一些包含有效重定向的请求,但只有last链中的一个我不想成为重定向。
我已经搜索过,并查看了重载.GetAsync(url, ...)
,并查看了属性和方法HttpClient
,但目前还没有找到解决办法。
这可能吗?
问题询问是否可以在以下重定向上完成逐案基础。虽然对于许多常见情况确实有用,但我发现现有的答案在这方面缺乏。
以下实现允许通过谓词根据实际情况来决定是否遵循重定向。
解决方案是重写 HttpClientHandler 的 SendAsync() 方法。
using System;
using System.Net;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
namespace HttpClientCustomRedirectBehavior
{
static class Program
{
private const string REDIRECTING_URL = "http://stackoverflow.com/";
static async Task Main(string[] args)
{
HttpMessageHandler followRedirectAlwaysHandler = new RestrictedRedirectFollowingHttpClientHandler(
response => true);
HttpMessageHandler followRedirectOnlyToSpecificHostHandler = new RestrictedRedirectFollowingHttpClientHandler(
response => response.Headers.Location.Host == "example.com");
HttpResponseMessage response;
using (HttpClient followRedirectAlwaysHttpClient = new HttpClient(followRedirectAlwaysHandler))
{
response = await followRedirectAlwaysHttpClient.GetAsync(REDIRECTING_URL);
Console.WriteLine(response.StatusCode); // OK
}
using (HttpClient followRedirectOnlyToSpecificHostHttpClient = new HttpClient(followRedirectOnlyToSpecificHostHandler))
{
response = await followRedirectOnlyToSpecificHostHttpClient.GetAsync(REDIRECTING_URL);
Console.WriteLine(response.StatusCode); // Moved
}
followRedirectOnlyToSpecificHostHandler = new RestrictedRedirectFollowingHttpClientHandler(
response => response.Headers.Location.Host == "stackoverflow.com");
using (HttpClient followRedirectOnlyToSpecificHostHttpClient = new HttpClient(followRedirectOnlyToSpecificHostHandler))
{
response = await followRedirectOnlyToSpecificHostHttpClient.GetAsync(REDIRECTING_URL);
Console.WriteLine(response.StatusCode); // OK
}
}
}
public class RestrictedRedirectFollowingHttpClientHandler : HttpClientHandler
{
private static readonly HttpStatusCode[] redirectStatusCodes = new[] {
HttpStatusCode.Moved,
HttpStatusCode.Redirect,
HttpStatusCode.RedirectMethod,
HttpStatusCode.TemporaryRedirect,
HttpStatusCode.PermanentRedirect
};
private readonly Predicate<HttpResponseMessage> isRedirectAllowed;
public override bool SupportsRedirectConfiguration { get; }
public RestrictedRedirectFollowingHttpClientHandler(Predicate<HttpResponseMessage> isRedirectAllowed)
{
AllowAutoRedirect = false;
SupportsRedirectConfiguration = false;
this.isRedirectAllowed = response => {
return Array.BinarySearch(redirectStatusCodes, response.StatusCode) >= 0
&& isRedirectAllowed.Invoke(response);
};
}
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
int redirectCount = 0;
HttpResponseMessage response = await base.SendAsync(request, cancellationToken).ConfigureAwait(false);
while (isRedirectAllowed.Invoke(response)
&& (response.Headers.Location != request.RequestUri || response.StatusCode == HttpStatusCode.RedirectMethod && request.Method != HttpMethod.Get)
&& redirectCount < this.MaxAutomaticRedirections)
{
if (response.StatusCode == HttpStatusCode.RedirectMethod)
{
request.Method = HttpMethod.Get;
}
request.RequestUri = response.Headers.Location;
response = await base.SendAsync(request, cancellationToken).ConfigureAwait(false);
++redirectCount;
}
return response;
}
}
}
Main 方法显示了三个示例请求http://stackoverflow.com(这是一个重定向到的 URIhttps://stackoverflow.com):
- 第一个 GET 请求将遵循重定向,因此我们会看到状态代码OK对重定向请求的响应,因为处理程序被配置为遵循所有重定向。
- 第二个 GET 请求不会遵循重定向,因此我们会看到状态代码Moved,因为处理程序被配置为仅遵循到主机 example.com 的重定向。
- 第三个 GET 请求将遵循重定向,因此我们会看到状态代码OK对重定向请求的响应,因为处理程序被配置为专门遵循到主机 stackoverflow.com 的重定向。
当然,您可以用任何自定义逻辑替换谓词。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)