C# -  Como incluir headers no request com HttpClient


  Hoje veremos como podemos incluir headers no request usando o HttpClient em uma aplicação  C#.

A classe HttpClient do namespace System.Net.Http envia requests HTTP e recebe responses HTTP de um recurso identificado por uma URI.

A recomendação de uso deste recurso é usar uma instância HttpClient estática ou singleton com PooledConnectionLifetime definido para o intervalo desejado, como dois minutos, dependendo das alterações de DNS esperadas. Isso resolve os problemas de esgotamento de porta e alterações de DNS sem adicionar a sobrecarga de IHttpClientFactory. Se você precisar zombar de seu manipulador, poderá registrá-lo separadamente.

Usando IHttpClientFactory, você pode ter vários clientes configurados de forma diferente para diferentes casos de uso. No entanto, esteja ciente de que os clientes criados pela factory devem ter vida curta e, uma vez que o cliente é criado, a fábrica não tem mais controle sobre ele.

Para mais detalhes veja o artigo : ASP.NET Core - Usando o HttpClientFactory

Incluindo Headers do request

Exitem duas maneiras de incluir headers em um request usando o HttpClient:

  1. Incluir headers para todos os request usando HttpClient.DefaultRequestHeaders;
  2. Incluir headers por request usando HttpRequestMessage.Headers.

Vamos iniciar com a primeira forma.

1- Incluindo um header imutável para todos os requests

Digamos que você esteja adicionando um header de chave de API. Ele precisa ser incluído em todas os requests e o valor não será alterado.

Para adicionar esse header no request, você pode usar HttpClient.DefaultRequestHeaders ao inicializar a instância HttpClient, da seguinte forma :

public class ServiceNumerosAleatorios
{
 
private readonly HttpClient HttpClient;
 
private const string key = "xyz@123";

 
public ServiceNumerosAleatorios()
  {
     HttpClient =
new HttpClient();
     HttpClient.DefaultRequestHeaders.Add(
"ApiKey", key);
  }

 
public async Task<string> GetNumeroAleatorio()
  {
    
var response = await HttpClient.GetAsync(GetNumeroAleatorioUrl);
     response.EnsureSuccessStatusCode();
    
return await response.Content.ReadAsStringAsync();
  }

}

A seguir temos o resultado no Fiddler :

GET https://localhost:12345/NumeroAleatorio HTTP/1.1
Host: localhost:12345
ApiKey: xyz@123

2 - Adicionar um cabeçalho por request

Para adicionar um cabeçalho por request, usamos HttpRequestMessage.Headers + HttpClient.SendAsync(), assim:

public class ServiceNumerosAleatorios
{
 
private readonly HttpClient HttpClient;
 
private const string numeroAleatorioUrl = "https://localhost:12345/NumeroAleatorio";

 
public ServiceNumerosAleatorios()
  {
    HttpClient =
new HttpClient();
  }

  public
async Task<string> GetRandomNumber(string Token)
  {
   
using (var request = new HttpRequestMessage(HttpMethod.Get, numeroAleatorioUrl))
    {
       request.Headers.Authorization =
new AuthenticationHeaderValue("Bearer", Token);
      
var response = await HttpClient.SendAsync(request);
       response.EnsureSuccessStatusCode();
      
return await response.Content.ReadAsStringAsync();
     }
   }
}

Em primeiro lugar é uma prática recomendada usar uma única instância HttpClient para vários request. Como você está usando uma única instância, não use HttpClient.DefaultRequestHeaders para cabeçalhos que precisam ser aplicados por request. Não é thread-safe. É por isso que você deve usar HttpRequestMessage.Headers.

Em segundo lugar, você deve usar HttpClient.SendAsync() para enviar a solicitação porque não há sobrecargas de GetAsync() / PostAsync() que usam um parâmetro HttpRequestMessage.

Usando o método GetWithHeadersAsync() para headers por request

Os métodos HttpClient.GetAsync() / PostAsync() são métodos de conveniência. Seria bom se houvesse sobrecargas deles que aceitassem uma lista de headers por request, mas não há.

Se você não quiser ter HttpRequestMessage + SendAsync() em todo lugar, você pode abstrair essa lógica usando métodos de extensão. Aqui está um exemplo:

public static class HttpClientExtensions
{
  
public static async Task<HttpResponseMessage> GetWithHeadersAsync(
    this HttpClient httpClient, string requestUri,
    Dictionary<
string, string> headers)
   {
    
using (var request = new HttpRequestMessage(HttpMethod.Get, requestUri))
     {
      
foreach (var header in headers)
       {
          request.Headers.Add(header.Key, header.Value);
       }
      
return await httpClient.SendAsync(request);
     }
   }
}

Podemos usar o método de extensão de maneira semelhante ao GetAsync():

public async Task<string> GetNumeroAleatorio(string Token)
{
 
var response = await HttpClient.GetWithHeadersAsync(numeroAleatorioUrl,
                          
new Dictionary<string, string>()
   {
      [
"Authorization"] = $"Bearer {Token}"
   });

    response.EnsureSuccessStatusCode();
   
return await response.Content.ReadAsStringAsync();
}

Este é apenas um método de extensão e podemos usar isso como ponto de partida e a seguir adicionar métodos de extensão para todas as possíveis sobrecargas de GetAsync() ou PostAsync().

Usar as propriedades HttpRequestHeaders para adicionar cabeçalhos comuns

Você pode adicionar qualquer cabeçalho usando .Add(key, value). Para cabeçalhos comuns, como Authorization, você também pode adicionar o cabeçalho por meio de propriedades em HttpRequestHeaders. Isso pode ajudá-lo a evitar erros e melhorar a legibilidade.

Por exemplo, podemos adicionar o cabeçalho Authorization nestas duas formas equivalentes:

//opção 1
request.Headers.Add(
"Authorization", $"Bearer {Token}");

//Opção 2 - Usando o a propriedade header
request.Headers.Authorization =
new AuthenticationHeaderValue(scheme: "Bearer", parameter: Token);
 

E estamos conversados...

"O sumo sacerdote lhe tornou a perguntar, e disse-lhe: És tu o Cristo, Filho do Deus Bendito?
E Jesus disse-lhe: Eu o sou, e vereis o Filho do homem assentado à direita do poder de Deus, e vindo sobre as nuvens do céu."
Marcos 14:61-62

Referências:


José Carlos Macoratti