Partager via


HttpClientFactory utilise SocketsHttpHandler comme gestionnaire principal

HttpClientFactory vous permet de configurer un HttpMessageHandler pipeline pour les objets nommés et typés HttpClient . Le gestionnaire le plus interne, ou celui qui envoie réellement la requête sur le câble, est appelé gestionnaire principal. S’il n’est pas configuré, ce gestionnaire était toujours un HttpClientHandler. Bien que le gestionnaire principal par défaut soit un détail d’implémentation, il y avait des utilisateurs qui en dépendent. Par exemple, certains utilisateurs castent le gestionnaire principal pour HttpClientHandler définir des propriétés telles que ClientCertificates, UseCookieset UseProxy.

Avec cette modification, le gestionnaire principal par défaut est une SocketsHttpHandler plateforme qui la prend en charge. Sur d’autres plateformes, par exemple .NET Framework, HttpClientHandler continuent d’être utilisées.

SocketsHttpHandler dispose désormais également de la présélection de propriété PooledConnectionLifetime pour correspondre à la HandlerLifetime valeur. (Elle reflète la dernière valeur, si HandlerLifetime elle a été configurée par l’utilisateur).

Version introduite

.NET 9 Preview 6

Comportement précédent

Le gestionnaire principal par défaut était HttpClientHandler. Le cast pour mettre à HttpClientHandler jour les propriétés s’est produit pour fonctionner.

services.AddHttpClient("test")
    .ConfigurePrimaryHttpMessageHandler((h, _) =>
    {
        ((HttpClientHandler)h).UseCookies = false;
    });

// This worked.
var client = httpClientFactory.CreateClient("test");

Nouveau comportement

Sur les plateformes où SocketsHttpHandler il est pris en charge, le gestionnaire principal par défaut est désormais SocketsHttpHandler défini PooledConnectionLifetime sur la HandlerLifetime valeur. Le cast pour mettre à HttpClientHandler jour les propriétés lève un InvalidCastException.

Par exemple, le même code de la section Précédent du comportement lève désormais un InvalidCastException:

System.InvalidCastException : Impossible de convertir l’objet de type « System.Net.Http.SocketsHttpHandler » en type « System.Net.Http.HttpClientHandler ».

Type de changement cassant

Ce changement est un changement de comportement.

Raison du changement

L’un des problèmes HttpClientFactory les plus courants rencontrés par les utilisateurs est qu’un ou Typed un Named client est capturé par erreur dans un service singleton, ou, en général, stocké quelque part pendant une période plus longue que celle spécifiéeHandlerLifetime. Étant donné que HttpClientFactory vous ne pouvez pas faire pivoter de tels gestionnaires, ils risquent de ne pas respecter les modifications DNS.

Ce problème peut être atténué à l’aide SocketsHttpHandlerde , qui a une option de contrôle PooledConnectionLifetime. De même que HandlerLifetime, la durée de vie de la connexion mise en pool permet de recréer régulièrement des connexions pour récupérer des modifications DNS, mais à un niveau inférieur. Un client avec PooledConnectionLifetime configuration peut être utilisé en toute sécurité en tant que singleton.

Malheureusement, il est facile et apparemment « intuitif » d’injecter un Typed client dans un singleton. Mais il est difficile d’avoir un type de contrôle ou d’analyseur pour s’assurer HttpClient qu’il n’est pas capturé quand il n’était pas censé être capturé. Il est également difficile de résoudre les problèmes résultants. Ainsi, en tant que mesure préventive , pour réduire l’impact potentiel des modèles d’utilisation erronés, l’atténuation SocketsHttpHandler est désormais appliquée par défaut.

Cette modification affecte uniquement les cas où le client n’a pas été configuré par l’utilisateur final pour utiliser un fichier personnalisé PrimaryHandler (par exemple, via ConfigurePrimaryHttpMessageHandler<THandler>(IHttpClientBuilder)).

Il existe trois options pour contourner le changement cassant :

  • Spécifiez et configurez explicitement un gestionnaire principal pour chacun de vos clients :

    services.AddHttpClient("test")
      .ConfigurePrimaryHttpMessageHandler(() => new HttpClientHandler() { UseCookies = false });
    
  • Remplacez le gestionnaire principal par défaut pour tous les clients à l’aide ConfigureHttpClientDefaults(IServiceCollection, Action<IHttpClientBuilder>)de :

    services.ConfigureHttpClientDefaults(b =>
      b.ConfigurePrimaryHttpMessageHandler(() => new HttpClientHandler() { UseCookies = false }));
    
  • Dans l’action de configuration, recherchez à la fois HttpClientHandler et SocketsHttpHandler:

    services.AddHttpClient("test")
      .ConfigurePrimaryHttpMessageHandler((h, _) =>
      {
          if (h is HttpClientHandler hch)
          {
              hch.UseCookies = false;
          }
    
          if (h is SocketsHttpHandler shh)
          {
              shh.UseCookies = false;
          }
      });
    

API affectées