Freigeben über


HttpClientFactory verwendet SocketsHttpHandler als primären Handler

HttpClientFactory ermöglicht es Ihnen, eine HttpMessageHandler Pipeline für benannte und typierte HttpClient Objekte zu konfigurieren. Der innerste Handler oder der Handler, der die Anforderung tatsächlich an das Kabel sendet, wird als primärer Handler bezeichnet. Wenn sie nicht konfiguriert ist, war dieser Handler zuvor immer ein HttpClientHandler. Während der primäre Standardhandler ein Implementierungsdetails ist, gab es Benutzer, die davon abhängig waren. Beispielsweise wandeln einige Benutzer den primären Handler um, um HttpClientHandler Eigenschaften wie ClientCertificates, UseCookiesund UseProxy.

Bei dieser Änderung ist der primäre Standardhandler ein SocketsHttpHandler auf Plattformen, die ihn unterstützen. Auf anderen Plattformen, z. B. .NET Framework, HttpClientHandler wird weiterhin verwendet.

SocketsHttpHandler verfügt nun auch über die Voreinstellung der PooledConnectionLifetime Eigenschaft, um dem HandlerLifetime Wert zu entsprechen. (Er gibt den neuesten Wert wieder, wenn HandlerLifetime er vom Benutzer konfiguriert wurde).

Eingeführt in Version

.NET 9 Preview 6

Vorheriges Verhalten

Der primäre Standardhandler war HttpClientHandler. Umwandlung, um HttpClientHandler die Eigenschaften zu aktualisieren, funktionierten.

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

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

Neues Verhalten

Auf Plattformen, auf denen SocketsHttpHandler unterstützt wird, ist der primäre Standardhandler jetzt SocketsHttpHandler auf PooledConnectionLifetime den HandlerLifetime Wert festgelegt. Das Umwandeln, um HttpClientHandler die Eigenschaften zu aktualisieren, löst ein InvalidCastException.

Beispielsweise löst derselbe Code aus dem Abschnitt "Vorheriges Verhalten " jetzt folgendes aus InvalidCastException:

System.InvalidCastException: Objekt vom Typ 'System.Net.Http.SocketsHttpHandler' kann nicht in den Typ 'System.Net.Http.HttpClientHandler' umwandeln.

Typ des Breaking Changes

Diese Änderung ist eine Verhaltensänderung.

Grund für die Änderung

Eines der häufigsten Probleme, HttpClientFactory bei denen Benutzer auftreten, besteht darin, dass ein Named oder Typed der Client fälschlicherweise in einem Singleton-Dienst erfasst wird oder im Allgemeinen für einen Bestimmten Zeitraum gespeichert wird, der länger als der angegebene HandlerLifetimeZeitraum ist. Da HttpClientFactory solche Handler nicht gedreht werden können, respektieren sie möglicherweise keine DNS-Änderungen.

Dieses Problem kann mithilfe der Option SocketsHttpHandlerzum Steuern PooledConnectionLifetimeabgemildert werden. Ähnlich wie HandlerLifetimebei der Lebensdauer der poolgebundenen Verbindung können Verbindungen regelmäßig neu aufgebaut werden, um DNS-Änderungen auf einer niedrigeren Ebene aufzunehmen. Ein Client mit PooledConnectionLifetime Einrichtung kann sicher als Singleton verwendet werden.

Leider ist es einfach und scheinbar "intuitiv", einen Typed Kunden in ein Singleton einzufügen. Es ist jedoch schwierig, eine Art von Überprüfung oder Analyse zu haben, um sicherzustellen, dass HttpClient sie nicht erfasst wird, wenn sie nicht erfasst werden soll. Es ist auch schwierig, die resultierenden Probleme zu beheben. Als präventive Maßnahme – um die potenziellen Auswirkungen fehlerhafter Nutzungsmuster zu minimieren – wird die SocketsHttpHandler Entschärfung jetzt standardmäßig angewendet.

Diese Änderung betrifft nur Fälle, in dem der Client vom Endbenutzer nicht für die Verwendung einer benutzerdefinierten PrimaryHandler (z. B. via ConfigurePrimaryHttpMessageHandler<THandler>(IHttpClientBuilder)) konfiguriert wurde.

Es gibt drei Optionen zum Umgehen der umbrechenden Änderung:

  • Geben Sie explizit einen primären Handler für jeden Ihrer Clients an und konfigurieren Sie sie:

    services.AddHttpClient("test")
      .ConfigurePrimaryHttpMessageHandler(() => new HttpClientHandler() { UseCookies = false });
    
  • Überschreiben Sie den primären Standardhandler für alle Clients, die Folgendes verwenden ConfigureHttpClientDefaults(IServiceCollection, Action<IHttpClientBuilder>):

    services.ConfigureHttpClientDefaults(b =>
      b.ConfigurePrimaryHttpMessageHandler(() => new HttpClientHandler() { UseCookies = false }));
    
  • Überprüfen Sie in der Konfigurationsaktion auf beide HttpClientHandler und SocketsHttpHandler:

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

Betroffene APIs