HttpClientFactory usa SocketsHttpHandler como manipulador primário
HttpClientFactory
Permite configurar um HttpMessageHandler pipeline para objetos nomeados e tipados HttpClient . O manipulador mais interno, ou aquele que realmente envia a solicitação na transmissão, é chamado de manipulador primário. Se não estiver configurado, esse manipulador era sempre um HttpClientHandler. Embora o manipulador primário padrão seja um detalhe de implementação, havia usuários que dependiam dele. Por exemplo, alguns usuários convertem o manipulador primário para HttpClientHandler
definir propriedades como ClientCertificates, UseCookiese UseProxy.
Com essa alteração, o manipulador primário padrão é um SocketsHttpHandler em plataformas que dão suporte a ele. Em outras plataformas, por exemplo, o .NET Framework HttpClientHandler continua a ser usado.
SocketsHttpHandler
agora também tem a predefinição de PooledConnectionLifetime propriedade para corresponder HandlerLifetime ao valor. (Reflete o valor mais recente, se HandlerLifetime
foi configurado pelo usuário).
Versão introduzida
.NET 9 Preview 6
Comportamento anterior
O manipulador primário padrão era HttpClientHandler
. Transmiti-lo para HttpClientHandler
atualizar as propriedades funcionou.
services.AddHttpClient("test")
.ConfigurePrimaryHttpMessageHandler((h, _) =>
{
((HttpClientHandler)h).UseCookies = false;
});
// This worked.
var client = httpClientFactory.CreateClient("test");
Novo comportamento
Nas plataformas em que SocketsHttpHandler
há suporte, o manipulador primário padrão agora SocketsHttpHandler
PooledConnectionLifetime
é set como o HandlerLifetime
valor. Convertê-lo para HttpClientHandler
atualizar as propriedades gera um InvalidCastException.
Por exemplo, o mesmo código da seção Comportamento anterior agora lança um InvalidCastException:
System.InvalidCastException: não é possível converter o objeto do tipo 'System.Net.Http.SocketsHttpHandler' para o tipo 'System.Net.Http.HttpClientHandler'.
Tipo de alteração interruptiva
Esta é uma alteração comportamental.
Motivo da alteração
Um dos problemas HttpClientFactory
mais comuns que os usuários enfrentam é quando um Named
cliente ou Typed
é capturado erroneamente em um serviço singleton ou, em geral, armazenado em algum lugar por um período de tempo maior do que o .HandlerLifetime Como HttpClientFactory
não é possível girar esses manipuladores, eles podem acabar não respeitando as alterações de DNS.
Esse problema pode ser atenuado usando SocketsHttpHandlero , que tem uma opção para controlar PooledConnectionLifetimeo . Da mesma forma que o HandlerLifetime, o tempo de vida da conexão em pool permite recriar regularmente conexões para captar alterações de DNS, mas em um nível inferior. Um cliente com PooledConnectionLifetime
configuração pode ser usado com segurança como um singleton.
Infelizmente, é fácil e aparentemente "intuitivo" injetar um Typed
cliente em um singleton. Mas é difícil ter qualquer tipo de verificação ou analisador para garantir que HttpClient
não seja capturado quando não deveria ser capturado. Também é difícil solucionar os problemas resultantes. Portanto, como medida preventiva, para minimizar o impacto potencial de padrões de uso incorretos, a SocketsHttpHandler
mitigação agora é aplicada por padrão.
Essa alteração afeta apenas os casos em que o cliente não foi configurado pelo usuário final para usar um personalizado PrimaryHandler (por exemplo, via ConfigurePrimaryHttpMessageHandler<THandler>(IHttpClientBuilder)).
Ação recomendada
Há três opções para contornar a alteração significativa:
Especifique e configure explicitamente um manipulador primário para cada um de seus clientes:
services.AddHttpClient("test") .ConfigurePrimaryHttpMessageHandler(() => new HttpClientHandler() { UseCookies = false });
Substitua o manipulador primário padrão para todos os clientes usando ConfigureHttpClientDefaults(IServiceCollection, Action<IHttpClientBuilder>):
services.ConfigureHttpClientDefaults(b => b.ConfigurePrimaryHttpMessageHandler(() => new HttpClientHandler() { UseCookies = false }));
Na ação de configuração, verifique se há e
HttpClientHandler
SocketsHttpHandler
:services.AddHttpClient("test") .ConfigurePrimaryHttpMessageHandler((h, _) => { if (h is HttpClientHandler hch) { hch.UseCookies = false; } if (h is SocketsHttpHandler shh) { shh.UseCookies = false; } });