链接在 FlurlClient 上的多个工厂方法

Multiple factory methods chained on FlurlClient

我正在尝试通过 FlurlClient 向某些网站提出一些请求。 但是我需要链接一些我在工厂里写的方法。

我使用 方法创建 ProxyAllowAutoRedirect 工厂。

允许自动重定向扩展:

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(); 

那么,如何使用 AllowAutoRedirectProxy 这两种方法只得到一个 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,希望你只做一次(每个客户端)而不是问题。