链接在 FlurlClient 上的多个工厂方法
Multiple factory methods chained on FlurlClient
我正在尝试通过 FlurlClient
向某些网站提出一些请求。
但是我需要链接一些我在工厂里写的方法。
我使用 方法创建 Proxy
和 AllowAutoRedirect
工厂。
允许自动重定向扩展:
public static IFlurlClient AllowAutoRedirect(this IFlurlClient fc, bool allowAutoRedirect)
{
fc.Settings.HttpClientFactory = new CustomFlurlHttpClientFactory(allowAutoRedirect);
return fc;
}
代理扩展:
public static IFlurlClient Proxy(this IFlurlClient fc, DML.Proxy proxy)
{
fc.Settings.HttpClientFactory = new CustomFlurlHttpClientFactory(proxy);
return fc;
}
最后这是我的工厂方法
private Proxy _proxy;
private bool? _allowAutoRedirect;
public CustomFlurlHttpClientFactory(Proxy proxy)
{
_proxy = proxy;
}
public CustomFlurlHttpClientFactory (bool? allowAutoRedirect)
{
_allowAutoRedirect = allowAutoRedirect;
}
public override HttpClient CreateHttpClient(HttpMessageHandler handler)
{
return base.CreateHttpClient(handler);
}
public override HttpMessageHandler CreateMessageHandler()
{
if(_proxy != null)
return ProxyClientHandlerConfiguration();
if (_allowAutoRedirect != null)
return AutoRedirectClientHandlerConfiguration();
return base.CreateMessageHandler();
}
private HttpClientHandler AutoRedirectClientHandlerConfiguration() => new HttpClientHandler { AllowAutoRedirect = _allowAutoRedirect ?? true };
private HttpClientHandler ProxyClientHandlerConfiguration() =>
new HttpClientHandler {
Proxy = new WebProxy {
Address = _proxy.GetFullUri(),
BypassProxyOnLocal = true,
UseDefaultCredentials = _proxy.UseDefaultCredentials()
},
UseProxy = true
};
但是在创建客户端时,只有第二种方法(Proxy)正确执行。
我知道当我调用 AllowAutoRedirect
时,它 returns 一个新的 HttpClientHandler
,当 Proxy
被调用时,它覆盖返回的 HttClientHandler
通过 AllowAutoRedirect
var cli = new FlurlClient(url)
.WithHeaders(headers)
.WithCookies(cookies)
.AllowAutoRedirect(false) /*Custom Factory Method*/
.Proxy(proxy) /*Custom Factory Method*/
.EnableCookies();
那么,如何使用 AllowAutoRedirect
和 Proxy
这两种方法只得到一个 HttpClientHandler
?
这里的问题是你的扩展方法每次都用一个新的工厂覆盖现有的工厂,所以最后一个总是 "win"。您需要编辑自定义工厂(如果存在),而不是替换它。开始使工厂可编辑。像这样:
public class CustomHttpClientFactory : DefaultHttpClientFactory
{
public bool? AutoRedirect { get; set; }
public Proxy Proxy { get; set; }
public override HttpMessageHandler CreateMessageHandler()
{
var handler = new HttpClientHandler();
if (AutoRedirect != null)
handler.AllowAutoRedirect = AutoRedirect;
if (Proxy != null) {
handler.Proxy = new WebProxy { ... };
handler.UseProxy = true;
}
return handler;
}
}
那么您的扩展方法应该如下所示:
public static IFlurlClient AllowAutoRedirect(this IFlurlClient fc, bool allowAutoRedirect)
{
var fac = fc.Settings.HttpClientFactory as CustomHttpClientFactory ??
new CustomHttpClientFactory();
fac.AutoRedirect = allowAutoRedirect;
fc.Settings.HttpClientFactory = fac;
return fc;
}
public static IFlurlClient Proxy(this IFlurlClient fc, Proxy proxy)
{
var fac = fc.Settings.HttpClientFactory as CustomHttpClientFactory ??
new CustomHttpClientFactory();
fac.Proxy = proxy;
fc.Settings.HttpClientFactory = fac;
return fc;
}
请注意,如果您从不同的线程为相同的 FlurlClient
使用这些扩展方法,您 可能 最终会出现竞争条件。但是因为他们是关于配置 client 而不是 request,希望你只做一次(每个客户端)而不是问题。
我正在尝试通过 FlurlClient
向某些网站提出一些请求。
但是我需要链接一些我在工厂里写的方法。
我使用 Proxy
和 AllowAutoRedirect
工厂。
允许自动重定向扩展:
public static IFlurlClient AllowAutoRedirect(this IFlurlClient fc, bool allowAutoRedirect)
{
fc.Settings.HttpClientFactory = new CustomFlurlHttpClientFactory(allowAutoRedirect);
return fc;
}
代理扩展:
public static IFlurlClient Proxy(this IFlurlClient fc, DML.Proxy proxy)
{
fc.Settings.HttpClientFactory = new CustomFlurlHttpClientFactory(proxy);
return fc;
}
最后这是我的工厂方法
private Proxy _proxy;
private bool? _allowAutoRedirect;
public CustomFlurlHttpClientFactory(Proxy proxy)
{
_proxy = proxy;
}
public CustomFlurlHttpClientFactory (bool? allowAutoRedirect)
{
_allowAutoRedirect = allowAutoRedirect;
}
public override HttpClient CreateHttpClient(HttpMessageHandler handler)
{
return base.CreateHttpClient(handler);
}
public override HttpMessageHandler CreateMessageHandler()
{
if(_proxy != null)
return ProxyClientHandlerConfiguration();
if (_allowAutoRedirect != null)
return AutoRedirectClientHandlerConfiguration();
return base.CreateMessageHandler();
}
private HttpClientHandler AutoRedirectClientHandlerConfiguration() => new HttpClientHandler { AllowAutoRedirect = _allowAutoRedirect ?? true };
private HttpClientHandler ProxyClientHandlerConfiguration() =>
new HttpClientHandler {
Proxy = new WebProxy {
Address = _proxy.GetFullUri(),
BypassProxyOnLocal = true,
UseDefaultCredentials = _proxy.UseDefaultCredentials()
},
UseProxy = true
};
但是在创建客户端时,只有第二种方法(Proxy)正确执行。
我知道当我调用 AllowAutoRedirect
时,它 returns 一个新的 HttpClientHandler
,当 Proxy
被调用时,它覆盖返回的 HttClientHandler
通过 AllowAutoRedirect
var cli = new FlurlClient(url)
.WithHeaders(headers)
.WithCookies(cookies)
.AllowAutoRedirect(false) /*Custom Factory Method*/
.Proxy(proxy) /*Custom Factory Method*/
.EnableCookies();
那么,如何使用 AllowAutoRedirect
和 Proxy
这两种方法只得到一个 HttpClientHandler
?
这里的问题是你的扩展方法每次都用一个新的工厂覆盖现有的工厂,所以最后一个总是 "win"。您需要编辑自定义工厂(如果存在),而不是替换它。开始使工厂可编辑。像这样:
public class CustomHttpClientFactory : DefaultHttpClientFactory
{
public bool? AutoRedirect { get; set; }
public Proxy Proxy { get; set; }
public override HttpMessageHandler CreateMessageHandler()
{
var handler = new HttpClientHandler();
if (AutoRedirect != null)
handler.AllowAutoRedirect = AutoRedirect;
if (Proxy != null) {
handler.Proxy = new WebProxy { ... };
handler.UseProxy = true;
}
return handler;
}
}
那么您的扩展方法应该如下所示:
public static IFlurlClient AllowAutoRedirect(this IFlurlClient fc, bool allowAutoRedirect)
{
var fac = fc.Settings.HttpClientFactory as CustomHttpClientFactory ??
new CustomHttpClientFactory();
fac.AutoRedirect = allowAutoRedirect;
fc.Settings.HttpClientFactory = fac;
return fc;
}
public static IFlurlClient Proxy(this IFlurlClient fc, Proxy proxy)
{
var fac = fc.Settings.HttpClientFactory as CustomHttpClientFactory ??
new CustomHttpClientFactory();
fac.Proxy = proxy;
fc.Settings.HttpClientFactory = fac;
return fc;
}
请注意,如果您从不同的线程为相同的 FlurlClient
使用这些扩展方法,您 可能 最终会出现竞争条件。但是因为他们是关于配置 client 而不是 request,希望你只做一次(每个客户端)而不是问题。