Delen via


HttpClientFactory maakt gebruik van SocketsHttpHandler als primaire handler

HttpClientFactory hiermee kunt u een HttpMessageHandler pijplijn configureren voor benoemde en getypte HttpClient objecten. De binnenste handler, of degene die de aanvraag daadwerkelijk op de draad verzendt, wordt een primaire handler genoemd. Als deze handler niet is geconfigureerd, was deze handler voorheen altijd een HttpClientHandler. Hoewel de standaard primaire handler een implementatiedetails is, waren er gebruikers die ervan afhankelijk waren. Sommige gebruikers casten bijvoorbeeld de primaire handler om HttpClientHandler eigenschappen zoals ClientCertificates, UseCookiesen UseProxy.

Met deze wijziging is de standaard primaire handler een SocketsHttpHandler op platforms die deze ondersteunen. Op andere platforms, bijvoorbeeld .NET Framework, HttpClientHandler wordt nog steeds gebruikt.

SocketsHttpHandler heeft nu ook de PooledConnectionLifetime vooraf ingestelde eigenschap die overeenkomt met de HandlerLifetime waarde. (Deze weerspiegelt de meest recente waarde, indien HandlerLifetime geconfigureerd door de gebruiker).

Versie geïntroduceerd

.NET 9 Preview 6

Vorig gedrag

De standaard primaire handler was HttpClientHandler. Casten om HttpClientHandler de eigenschappen bij te werken, werkten.

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

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

Nieuw gedrag

Op platforms waar SocketsHttpHandler wordt ondersteund, is de standaard primaire handler nu SocketsHttpHandler ingesteld PooledConnectionLifetime op de HandlerLifetime waarde. Casten om HttpClientHandler de eigenschappen bij te werken genereert een InvalidCastException.

Dezelfde code uit de sectie Vorig gedrag genereert nu bijvoorbeeld een InvalidCastException:

System.InvalidCastException: Kan het object van het type System.Net.Http.SocketsHttpHandler niet casten om 'System.Net.Http.HttpClientHandler' te typen.

Type wijziging die fouten veroorzaken

Deze wijziging is een gedragswijziging.

Reden voor wijziging

Een van de meest voorkomende problemen HttpClientFactory die gebruikers ondervinden, is wanneer een Named of Typed client per ongeluk wordt vastgelegd in een singleton-service, of, in het algemeen, ergens wordt opgeslagen gedurende een bepaalde periode die langer is dan de opgegeven HandlerLifetime. Omdat HttpClientFactory dergelijke handlers niet kunnen worden geroteerd, kunnen ze mogelijk geen DNS-wijzigingen respecteren.

Dit probleem kan worden verholpen met behulp van SocketsHttpHandler, die een optie heeft om te beheren PooledConnectionLifetime. Net als HandlerLifetimebij de levensduur van de poolverbinding kunnen verbindingen regelmatig opnieuw worden gemaakt om DNS-wijzigingen op te halen, maar op een lager niveau. Een client met PooledConnectionLifetime set-up kan veilig worden gebruikt als singleton.

Het is helaas gemakkelijk en schijnbaar "intuïtief" om een Typed client in een singleton te injecteren. Maar het is moeilijk om een soort controle of analyse te hebben om ervoor te zorgen dat HttpClient deze niet wordt vastgelegd wanneer het niet zou worden vastgelegd. Het is ook moeilijk om de resulterende problemen op te lossen. Als preventieve meting, om de mogelijke impact van onjuiste gebruikspatronen te minimaliseren, wordt de SocketsHttpHandler beperking nu standaard toegepast.

Deze wijziging is alleen van invloed op gevallen waarin de client niet is geconfigureerd door de eindgebruiker om een aangepaste toepassing PrimaryHandler te gebruiken (bijvoorbeeld via ConfigurePrimaryHttpMessageHandler<THandler>(IHttpClientBuilder)).

Er zijn drie opties om de wijziging die fouten veroorzaken te omzeilen:

  • Geef expliciet een primaire handler op en configureer deze voor elk van uw clients:

    services.AddHttpClient("test")
      .ConfigurePrimaryHttpMessageHandler(() => new HttpClientHandler() { UseCookies = false });
    
  • Overschrijf de standaard primaire handler voor alle clients met:ConfigureHttpClientDefaults(IServiceCollection, Action<IHttpClientBuilder>)

    services.ConfigureHttpClientDefaults(b =>
      b.ConfigurePrimaryHttpMessageHandler(() => new HttpClientHandler() { UseCookies = false }));
    
  • Controleer in de configuratieactie op beide HttpClientHandler en SocketsHttpHandler:

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

Betrokken API's