Cliente HTTP em C#: técnicas avançadas de trabalho com requisições

Treinador Online de Python para Iniciantes

Aprenda Python facilmente sem sobrecarga teórica. Resolva tarefas práticas com verificação automática e escreva código diretamente no navegador.

Start Course

Cliente HTTP em C#: fazendo requisições corretamente — nível avançado



No desenvolvimento moderno em .NET, o trabalho com requisições HTTP vai muito além da simples chamada de WebClient ou do básico HttpClient. Em nível avançado, é necessário considerar o gerenciamento do pool de conexões, o tratamento correto de erros, timeouts, políticas de repetição e execução assíncrona. Neste artigo, abordaremos as melhores práticas de trabalho com o cliente HTTP em C#, que ajudarão você a criar aplicações robustas e de alto desempenho.



1. Trabalho correto com HttpClient e pool de conexões



Um dos erros mais comuns é criar uma nova instância de HttpClient para cada requisição. Isso leva ao esgotamento de sockets (socket exhaustion) porque cada instância mantém uma conexão TCP aberta no estado TIME_WAIT.



Incorreto:

public async Task<string> GetDataAsync(string url){    using (var client = new HttpClient())    {        return await client.GetStringAsync(url);    }}


Correto: use uma única instância estática ou singleton de HttpClient.



public class HttpService{    private static readonly HttpClient _client = new HttpClient();

public async Task<string> GetDataAsync(string url) { return await _client.GetStringAsync(url); }}


Para um controle mais refinado, use IHttpClientFactory do pacote Microsoft.Extensions.Http. A fábrica gerencia o pool e reconecta automaticamente em caso de falhas de DNS.



// Em Startup.cs ou Program.csservices.AddHttpClient("MyClient", client =>{    client.BaseAddress = new Uri("https://api.example.com");    client.DefaultRequestHeaders.Add("User-Agent", "MyApp/1.0");});

// No serviçopublic class MyService{ private readonly IHttpClientFactory _httpClientFactory;

public MyService(IHttpClientFactory httpClientFactory) { _httpClientFactory = httpClientFactory; }

public async Task<string> GetDataAsync() { var client = _httpClientFactory.CreateClient("MyClient"); return await client.GetStringAsync("/data"); }}


2. Timeouts e cancelamento de requisições



Sem timeouts, seu cliente pode travar por tempo indeterminado. No HttpClient, existem dois mecanismos:



  • Timeout — timeout geral para toda a requisição.
  • CancellationToken — para cancelar a requisição externamente (por exemplo, o usuário fechou o aplicativo).


Defina o Timeout de forma razoável. Para a maioria das APIs, 10–30 segundos são adequados.



var client = new HttpClient{    Timeout = TimeSpan.FromSeconds(15)};

// Exemplo com CancellationTokenSourceusing var cts = new CancellationTokenSource(TimeSpan.FromSeconds(10));try{ var response = await client.GetAsync("https://slow-api.example.com", cts.Token);}catch (TaskCanceledException){ Console.WriteLine("Requisição cancelada por timeout.");}


Importante: Timeout e CancellationToken funcionam em conjunto. Se o CancellationToken disparar primeiro, a requisição é cancelada mais rapidamente.



3. Tratamento de erros e política de repetição (Retry)



Falhas de rede e erros temporários do servidor são comuns. Em vez de falhar imediatamente, implemente uma política de repetição com backoff exponencial. Para isso, a biblioteca Polly é excelente.



using Polly;using Polly.Extensions.Http;

// Definindo a política de repetiçãovar retryPolicy = HttpPolicyExtensions .HandleTransientHttpError() // 5xx, 408 .Or<HttpRequestException>() .WaitAndRetryAsync(3, retryAttempt => Tim

Blogs

Book Recommendations