IHttpClientFactory | CSharp
- IHttpClientFactory | CSharp
Visão Geral
Tradicionalmente, em aplicações .NET ao fazer chamadas HTTP geralmente se utilizava diretamente a classe HttpClient. Isso costuma gerar problemas de desempenho e de gerenciamento, como socket exhaustion (exaustão de soquetes).
O IHttpClientFactory, introduzido no .NET Core 2.1, fornece uma forma centralizada e mais segura de configurar e criar instâncias de HttpClient, gerenciando corretamente o ciclo de vida internamente.
Por que usar IHttpClientFactory?
Principais problemas que ele resolve
- Socket Exhaustion: Criar muitas instâncias de HttpClient, ou não reutilizar/injectar corretamente, pode levar ao esgotamento de soquetes. O HttpClient pode manter conexões subjacentes vivas e não fechadas.
IHttpClientFactorycuida dos handlers por trás para evitar esse tipo de problema. - Configuração centralizada: Permite definir configurações (base address, headers, timeout) em um único local, para clientes HttpClient em diferentes cenários.
- Clientes nomeados (Named) e tipados (Typed): Permite definir diferentes configurações para diferentes finalidades — e injetar de forma adequada, ao invés de criar manualmente cada HttpClient.
Três formas de uso
O artigo apresenta 3 formas de usar IHttpClientFactory. Vamos documentar cada uma.
1. Uso simples – injetando IHttpClientFactory
Registro (por exemplo em Startup.cs ou Program.cs dependendo da versão .NET):
public void ConfigureServices(IServiceCollection services)
{
services.AddHttpClient();
}
Uso na classe de serviço:
public class WeatherService
{
private readonly IHttpClientFactory _httpClientFactory;
public WeatherService(IHttpClientFactory httpClientFactory)
{
_httpClientFactory = httpClientFactory;
}
public async Task<string> GetWeatherDataAsync(string city, string apiKey)
{
var httpClient = _httpClientFactory.CreateClient();
var url = $"https://api.openweathermap.org/data/2.5/weather?q={city}&appid={apiKey}";
var response = await httpClient.GetAsync(url);
if (response.IsSuccessStatusCode)
{
return await response.Content.ReadAsStringAsync();
}
return null;
}
}
Observações:
- Esse método permite reutilização automática do HttpClient criado, conforme a fábrica gerencia internamente.
- A URL completa foi usada na chamada (
BaseAddressnão foi definida no cliente). - Quando há poucas configurações diferentes, pode ser suficiente.
2. Named Clients (Clientes nomeados)
Permite registrar clientes HttpClient com nomes específicos, cada um com configuração própria.
Registro:
public void ConfigureServices(IServiceCollection services)
{
services.AddHttpClient("WeatherClient", client =>
{
client.BaseAddress = new Uri("https://api.openweathermap.org/");
client.DefaultRequestHeaders.Add("Accept", "application/json");
});
}
Uso:
public class WeatherService
{
private readonly IHttpClientFactory _httpClientFactory;
public WeatherService(IHttpClientFactory httpClientFactory)
{
_httpClientFactory = httpClientFactory;
}
public async Task<string> GetWeatherDataAsync(string city, string apiKey)
{
var httpClient = _httpClientFactory.CreateClient("WeatherClient");
var url = $"data/2.5/weather?q={city}&appid={apiKey}";
var response = await httpClient.GetAsync(url);
if (response.IsSuccessStatusCode)
{
return await response.Content.ReadAsStringAsync();
}
return null;
}
}
Vantagens:
- Configuração central (“WeatherClient”) tem BaseAddress, headers padronizados.
- O código de serviço reduz duplicação de URL base ou headers.
- Se tiver várias APIs ou clientes HTTP diferentes, cada um pode ter seu nome/configuração.
3. Typed Clients (Clientes tipados)
Aqui você define uma classe que encapsula o HttpClient específico, e registra esse cliente como um tipo no DI.
Definição da classe cliente:
public class WeatherClient
{
private readonly HttpClient _httpClient;
public WeatherClient(HttpClient httpClient)
{
_httpClient = httpClient;
}
public async Task<string> GetWeatherDataAsync(string city, string apiKey)
{
var url = $"data/2.5/weather?q={city}&appid={apiKey}";
var response = await _httpClient.GetAsync(url);
if (response.IsSuccessStatusCode)
{
return await response.Content.ReadAsStringAsync();
}
return null;
}
}
Registro no DI:
public void ConfigureServices(IServiceCollection services)
{
services.AddHttpClient<WeatherClient>(client =>
{
client.BaseAddress = new Uri("https://api.openweathermap.org/");
client.DefaultRequestHeaders.Add("Accept", "application/json");
});
}
Uso da classe cliente em outro serviço:
public class WeatherService
{
private readonly WeatherClient _weatherClient;
public WeatherService(WeatherClient weatherClient)
{
_weatherClient = weatherClient;
}
public async Task<string> GetWeatherDataAsync(string city, string apiKey)
{
return await _weatherClient.GetWeatherDataAsync(city, apiKey);
}
}
Benefícios:
- Encapsula a lógica HTTP específica para uma API ou serviço.
- Permite melhor separação de responsabilidades.
- Facilita testes e manutenção.
- Fornece configuração central como Named, mas com tipo forte.
Avisos / Boas práticas
- Evite injetar clientes tipados em serviços que tenham tempo de vida Singleton (singleton). O HttpClient pode não se comportar corretamente se for usado como singleton de forma errada.
- A fábrica gerencia internamente os handlers e pools de conexões. Não basta usar
using (new HttpClient())repetidamente — isso pode causar desgaste de recursos. - Configure adequadamente o
BaseAddress,DefaultRequestHeaders,Timeout,PolicyHandlers(ex: retry, circuit breaker) se necessário. - Nomear ou tipar clientes traz clareza e consistência — especialmente em aplicações com múltiplas APIs externas.
- Para cenários simples, pode bastar o primeiro modelo (injeção de
IHttpClientFactory), mas para aplicações maiores vale adotar Named ou Typed.
Resumo
IHttpClientFactoryé o “caminho recomendado” para criar e gerenciar instâncias HttpClient no .NET moderno.- Três formas principais: injetar
IHttpClientFactory, usar Named Clients, usar Typed Clients. - Ao aplicar essas abordagens corretamente, você obtém: melhor consumo de recursos, menos risco de exaustão de soquetes, configuração centralizada, maior manutenibilidade.
- Evite misturar lifetime de clientes tipados com serviços singleton de forma inadequada.