HttpClientFactory использует SocketsHttpHandler в качестве основного обработчика
HttpClientFactory
позволяет настроить HttpMessageHandler конвейер для именованных и типизированных HttpClient объектов. Внутренний обработчик или тот, который фактически отправляет запрос по проводу, называется основным обработчиком. Если этот обработчик не настроен, этот обработчик всегда HttpClientHandlerбыл. Хотя основной обработчик по умолчанию является подробным описанием реализации, существовали пользователи, которые зависели от него. Например, некоторые пользователи приведение основного обработчика для HttpClientHandler
задания свойств, таких как ClientCertificates, UseCookiesи UseProxy.
При этом изменении основной обработчик по умолчанию — это SocketsHttpHandler на платформах, поддерживающих его. Например, на других платформах платформа .NET Framework HttpClientHandler продолжает использоваться.
SocketsHttpHandler
теперь также имеет PooledConnectionLifetime предустановку свойства для сопоставления HandlerLifetime значения. (Оно отражает последнее значение, если HandlerLifetime
оно было настроено пользователем).
Представленные версии
.NET 9( предварительная версия 6)
Прежнее поведение
Основным обработчиком по умолчанию был HttpClientHandler
. Приведение к нему для HttpClientHandler
обновления свойств произошло.
services.AddHttpClient("test")
.ConfigurePrimaryHttpMessageHandler((h, _) =>
{
((HttpClientHandler)h).UseCookies = false;
});
// This worked.
var client = httpClientFactory.CreateClient("test");
Новое поведение
На платформах, где SocketsHttpHandler
поддерживается, основной обработчик по умолчанию теперь SocketsHttpHandler
имеет PooledConnectionLifetime
значение HandlerLifetime
. Приведение к нему для HttpClientHandler
обновления свойств вызывает исключение InvalidCastException.
Например, тот же код из раздела "Предыдущее поведение " теперь вызывает следующее InvalidCastException:
System.InvalidCastException: не удается привести объект типа System.Net.Http.SocketsHttpHandler для типа System.Net.Http.HttpClientHandler.
Тип критического изменения
Причина изменения
Одна из наиболее распространенных проблемHttpClientFactory
, с которыми пользователи могут столкнуться, заключается в том, что Named
Typed
клиент или клиент ошибочно фиксируется в одной службе или, как правило, хранится где-то в течение определенного периода времени, превышающего указанное.HandlerLifetime Так как HttpClientFactory
не удается повернуть такие обработчики, они могут в конечном итоге не учитывать изменения DNS.
Эта проблема может быть устранена с помощью SocketsHttpHandlerсредства управления PooledConnectionLifetime. HandlerLifetimeАналогично тому, время существования подключения в пуле позволяет регулярно воссоздать подключения для получения изменений DNS, но на более низком уровне. Клиент с PooledConnectionLifetime
настройкой можно безопасно использовать в качестве единого.
К сожалению, легко и, казалось бы, "интуитивно" внедрить Typed
клиента в одинарный. Но это трудно иметь какой-либо проверки или анализатора, чтобы убедиться HttpClient
, что он не был захвачен, когда он не должен быть захвачен. Кроме того, трудно устранить возникающие проблемы. Таким образом, в качестве профилактической меры , чтобы свести к минимуму потенциальное влияние ошибочных шаблонов использования, SocketsHttpHandler
устранение рисков теперь применяется по умолчанию.
Это изменение влияет только на случаи, когда клиент не был настроен конечным пользователем для использования пользовательского PrimaryHandler (например, через ConfigurePrimaryHttpMessageHandler<THandler>(IHttpClientBuilder)).
Рекомендуемое действие
Существует три варианта для решения критического изменения:
Явно укажите и настройте основной обработчик для каждого клиента:
services.AddHttpClient("test") .ConfigurePrimaryHttpMessageHandler(() => new HttpClientHandler() { UseCookies = false });
Перезапись основного обработчика по умолчанию для всех клиентов с помощью ConfigureHttpClientDefaults(IServiceCollection, Action<IHttpClientBuilder>):
services.ConfigureHttpClientDefaults(b => b.ConfigurePrimaryHttpMessageHandler(() => new HttpClientHandler() { UseCookies = false }));
В действии конфигурации проверьте оба
HttpClientHandler
иSocketsHttpHandler
:services.AddHttpClient("test") .ConfigurePrimaryHttpMessageHandler((h, _) => { if (h is HttpClientHandler hch) { hch.UseCookies = false; } if (h is SocketsHttpHandler shh) { shh.UseCookies = false; } });