Пользовательский HttpClientHandler, использующий FlurlClient, не использует ClientCertificate

Мне нужно добавить сертификат клиента в мои веб-запросы и попытаться достичь его следующим образом: Stackru

В конце этого ответа представлен "FlurlClient way". Использование и настройка FlurlClient вместо глобальной конфигурации FlurlHttp. Я пробовал это, но это не сработало.

Я создал новое консольное приложение .NET Core, чтобы показать вам проблему:

static void Main(string[] args)
{
   /****** NOT WORKING *******/
   try
   {
      IFlurlClient fc1 = new FlurlClient(url)
         .ConfigureClient(c => c.HttpClientFactory = new X509HttpFactory(GetCert()));

      fc1.WithHeader("User-Agent", userAgent)
         .WithHeader("Accept-Language", locale);

      dynamic ret1 = fc1.Url.AppendPathSegments(pathSegments).GetJsonAsync()
         .GetAwaiter().GetResult();
   }
   catch
   {
      // --> Exception: 403 FORBIDDEN
   }


   /****** NOT WORKING *******/
   try
   {
      IFlurlClient fc2 = new FlurlClient(url);

      fc2.Settings.HttpClientFactory = new X509HttpFactory(GetCert());

      fc2.WithHeader("User-Agent", userAgent)
         .WithHeader("Accept-Language", locale);

      dynamic ret2 = fc2.Url.AppendPathSegments(pathSegments).GetJsonAsync()
         .GetAwaiter().GetResult();
   }
   catch
   {
      // --> Exception: 403 FORBIDDEN
   }


   /****** WORKING *******/
   FlurlHttp.Configure(c =>
   {
      c.HttpClientFactory = new X509HttpFactory(GetCert());
   });

   dynamic ret = url.AppendPathSegments(pathSegments).GetJsonAsync()
      .GetAwaiter().GetResult();
   // --> OK
}

X509HttpFactory копируется из связанного ответа Stackru (но с использованием HttpClientHandler вместо WebRequestHandler):

public class X509HttpFactory : DefaultHttpClientFactory
{
   private readonly X509Certificate2 _cert;

   public X509HttpFactory(X509Certificate2 cert)
   {
      _cert = cert;
   }

   public override HttpMessageHandler CreateMessageHandler()
   {
      var handler = new HttpClientHandler();
      handler.ClientCertificates.Add(_cert);
      return handler;
   }
}

Таким образом, использование глобальной конфигурации FlurlHttp работает, а настройка FlurlClient не работает. Зачем?

1 ответ

Решение

Это все сводится к тому, что вы называете вещи:

  • fc.Url возвращает Url объект, который немного больше чем строительная вещь. Это не держит ссылку на FlurlClient, (Это позволяет Flurl существовать как библиотека создания URL-адресов независимо от Flurl.Http.)
  • Url.AppendPathSegments возвращает "это" Url,
  • Url.GetJsonAsync это метод расширения, который сначала создает FlurlClient, а затем использует его с текущим Url сделать HTTP-вызов.

Итак, как вы можете видеть, вы потеряли свою ссылку на fc на этапе 1 этого потока. 2 возможных решения:

1. Сначала создайте URL, затем плавно добавьте биты HTTP:

url
    .AppendPathSegments(...)
    .ConfigureClient(...)
    .WithHeaders(...)
    .GetJsonAsync();

2. ИЛИ, если вы хотите повторно использовать FlurlClient, "прикрепите" его к URL-адресу с помощью WithClient:

var fc = new FlurlClient()
    .ConfigureClient(...)
    .WithHeaders(...);

url
    .AppendPathSegments(...)
    .WithClient(fc)
    .GetJsonAsync();
Другие вопросы по тегам