HttpClientFactory usa SocketsHttpHandler come gestore primario
HttpClientFactory
consente di configurare una HttpMessageHandler pipeline per oggetti denominati e tipizzati HttpClient . Il gestore più interno, o quello che invia effettivamente la richiesta in transito, è denominato gestore primario. Se non è configurato, questo gestore era sempre un oggetto HttpClientHandler. Mentre il gestore primario predefinito è un dettaglio di implementazione, c'erano utenti che ne dipendevano. Ad esempio, alcuni utenti esegue il cast del gestore primario per HttpClientHandler
impostare proprietà come ClientCertificates, UseCookiese UseProxy.
Con questa modifica, il gestore primario predefinito è un oggetto SocketsHttpHandler sulle piattaforme che lo supportano. In altre piattaforme, ad esempio .NET Framework, HttpClientHandler continua a essere usato.
SocketsHttpHandler
ora ha anche la PooledConnectionLifetime proprietà preimpostata in modo che corrisponda al HandlerLifetime valore. (riflette il valore più recente, se HandlerLifetime
è stato configurato dall'utente).
Versione introdotta
.NET 9 Anteprima 6
Comportamento precedente
Il gestore primario predefinito è .HttpClientHandler
Eseguire il cast per HttpClientHandler
aggiornare le proprietà è stato eseguito correttamente.
services.AddHttpClient("test")
.ConfigurePrimaryHttpMessageHandler((h, _) =>
{
((HttpClientHandler)h).UseCookies = false;
});
// This worked.
var client = httpClientFactory.CreateClient("test");
Nuovo comportamento
Nelle piattaforme in cui SocketsHttpHandler
è supportato il gestore primario predefinito è ora SocketsHttpHandler
impostato PooledConnectionLifetime
sul HandlerLifetime
valore . Eseguire il cast per HttpClientHandler
aggiornare le proprietà genera un'eccezione InvalidCastException.
Ad esempio, lo stesso codice della sezione Comportamento precedente genera ora un'eccezione InvalidCastException:
System.InvalidCastException: impossibile eseguire il cast dell'oggetto di tipo 'System.Net.Http.SocketsHttpHandler' per digitare 'System.Net.Http.HttpClientHandler'.
Tipo di modifica che causa un'interruzione
Questa è una modifica funzionale.
Motivo della modifica
Uno dei problemi HttpClientFactory
più comuni riscontrati dagli utenti è quando un Named
client o Typed
viene erroneamente acquisito in un servizio singleton o, in generale, archiviato in un punto per un periodo di tempo maggiore rispetto a quello specificato HandlerLifetime. Poiché HttpClientFactory
non è possibile ruotare tali gestori, potrebbero non rispettare le modifiche DNS.
Questo problema può essere risolto usando SocketsHttpHandler, che dispone di un'opzione per controllare PooledConnectionLifetime. Analogamente a HandlerLifetime, la durata della connessione in pool consente di ricreare regolarmente le connessioni per raccogliere le modifiche DNS, ma a un livello inferiore. Un client con PooledConnectionLifetime
configurazione può essere usato in modo sicuro come singleton.
Purtroppo, è facile e apparentemente "intuitivo" inserire un Typed
client in un singleton. Ma è difficile avere qualsiasi tipo di controllo o analizzatore per assicurarsi HttpClient
che non venga acquisito quando non doveva essere acquisito. È anche difficile risolvere i problemi risultanti. Pertanto, come misura preventiva, per ridurre al minimo il potenziale impatto dei modelli di utilizzo errati, la SocketsHttpHandler
mitigazione viene ora applicata per impostazione predefinita.
Questa modifica influisce solo sui casi in cui il client non è stato configurato dall'utente finale per l'uso di un personalizzato PrimaryHandler ,ad esempio tramite ConfigurePrimaryHttpMessageHandler<THandler>(IHttpClientBuilder).
Azione consigliata
Esistono tre opzioni per aggirare la modifica che causa un'interruzione:
Specificare e configurare in modo esplicito un gestore primario per ognuno dei client:
services.AddHttpClient("test") .ConfigurePrimaryHttpMessageHandler(() => new HttpClientHandler() { UseCookies = false });
Sovrascrivere il gestore primario predefinito per tutti i client usando ConfigureHttpClientDefaults(IServiceCollection, Action<IHttpClientBuilder>):
services.ConfigureHttpClientDefaults(b => b.ConfigurePrimaryHttpMessageHandler(() => new HttpClientHandler() { UseCookies = false }));
Nell'azione di configurazione verificare sia che
HttpClientHandler
SocketsHttpHandler
:services.AddHttpClient("test") .ConfigurePrimaryHttpMessageHandler((h, _) => { if (h is HttpClientHandler hch) { hch.UseCookies = false; } if (h is SocketsHttpHandler shh) { shh.UseCookies = false; } });