Несколько фабричных методов, связанных в FlurlClient - PullRequest
0 голосов
/ 15 октября 2019

Я пытаюсь сделать запрос через FlurlClient на некоторые сайты. Но мне нужно объединить некоторые методы, которые я написал на фабрике.

Я использую этот подход для создания фабрики Proxy и AllowAutoRedirect.

Расширение 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, он возвращает новый HttpClientHandler, а когда вызывается Proxy, онпереопределяет HttClientHandler, возвращаемое AllowAutoRedirect

var cli = new FlurlClient(url)
             .WithHeaders(headers)
             .WithCookies(cookies)
             .AllowAutoRedirect(false) /*Custom Factory Method*/
             .Proxy(proxy) /*Custom Factory Method*/
             .EnableCookies(); 

Итак, как я могу получить только один HttpClientHandler, используя оба метода, AllowAutoRedirect и Proxy?

1 Ответ

1 голос
/ 16 октября 2019

Проблема здесь в том, что ваши методы расширения каждый раз перезаписывают существующую фабрику новой, поэтому последняя всегда будет «побеждать». Вам нужно отредактировать пользовательскую фабрику (если она существует), а не заменить ее. Начните делать фабрику редактируемой. Примерно так:

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 из разных потоков. Но поскольку речь идет о настройке клиента , а не запроса , надеюсь, вы просто делаете это один раз (для каждого клиента), и это не проблема.

...