C# -  Como ler o Header do Response com HttpClient


  Hoje veremos como podemos ler o Header do Response usando o HttpClient em uma aplicação C#.

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

Uma instância HttpClient é uma coleção de configurações aplicadas a todas os requests executados por essa instância, e cada instância usa seu próprio pool de conexão, que isola suas solicitações de outras. (A partir do .NET Core 2.1, a classe SocketsHttpHandler fornece a implementação, tornando o comportamento consistente em todas as plataformas.)

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

Lendo Headers do response

Quando você envia uma solicitação com HttpClient, ela retorna uma HttpResponseMessage, e, neste caso você pode ler os cabeçalhos de resposta por meio da propriedade HttpResponseMessage.Headers:

using System.Linq;
var response = await httpClient.GetAsync("https://localhost:12345/teste/site");
foreach (var header in response.Headers)
{
     Console.WriteLine($"{header.Key}={header.Value.First()}");
}

Este código exibe o header do response no formato a seguir:

Date=Wed, 28 Dec 2022 18:48:54 GMT
Server=Kestrel
Cache-Control=max-age=60
Transfer-Encoding=chunked

Os headers do response são pares de chave-valor(es), e,  quando a resposta chega, os cabeçalhos são carregados na propriedade Headers (que é do tipo HttpResponseHeaders). Isso analisa os cabeçalhos e fornece uma interface para acessá-los como objetos KeyValuePair<string, IEnumerable<string>>.

O exemplo acima mostrou como percorrer os cabeçalhos. Neste artigo, veremos como ler cabeçalhos específicos – cabeçalhos personalizados, cabeçalhos comuns (ex: Cache-Control) e cabeçalhos de conteúdo (ex: Content-Type).

Lendo Headers específicos

Os headers específicos são headers que já são esperados no response e que devemos identificar.

1- Usando Headers.TryGetValues()

using System.Linq;
using System.Net.Http;
var response = await httpClient.GetAsync("https://localhost:12345/teste/site");
if (response.Headers.TryGetValues("X-Teste-111", out IEnumerable<string> valorHeaderList))
{
    var valorHeader = valorHeaderList.First();
    //trata o valor do header
}
else
{
    //O header não existe
}

2- Usando Headers.Contains() mais Headers.GetValues()

var response = await httpClient.GetAsync("https://localhost:12345/teste/site");

if (response.Headers.Contains("X-Teste-111"))
{
  
var valorHeader = response.Headers.GetValues("X-Teste-111").First();
 
//trata o valor do header
}
...

Como GetValues() vai lançar uma exceção se o cabeçalho não existir a recomendação é sempre usar também Contains().

Os cabeçalhos podem ter vários valores, e é por isso que sempre retorna IEnumerable<string>; este é o motivo porque estamos usando First(), para obter o primeiro valor (mesmo que seja o único valor).

Lendo headers de response comuns

Existem muitos cabeçalhos de resposta HTTP comuns (ex: Cache-Control, Server, Retry-After). Alguns dos cabeçalhos de resposta comuns são analisados em propriedades fortemente tipadas (ex: Headers.CacheControl). Se você precisar ler um cabeçalho comum, verifique se há propriedade para ele em Headers e a utilize.

Por exemplo, digamos que você queira ler o cabeçalho Cache-Control. Você pode usar a propriedade Headers.CacheControl para fazer isso :

var response = await httpClient.GetAsync("https://localhost:12345/teste/site");

var maxAge = response.Headers.CacheControl?.MaxAge;

//usar o valor do header
 

Aqui max-age é a quantidade máxima de tempo especificado em número de segundos.(MDN)

Se o cabeçalho estiver ausente, a propriedade será nula. Certifique-se de lidar com nulos adequadamente para evitar um NullReferenceException de tempo de execução.

Se não houver uma propriedade conveniente em Headers para o cabeçalho que você está tentando ler, use TryGetValues() / GetValues() (conforme foi mostrado acima).

Lendo cabeçalhos de conteúdo

Você pode acessar os cabeçalhos de conteúdo por meio da propriedade HttpResponseMessage.Content.Headers.

Por exemplo, digamos que você queira verificar o Content-Type para determinar como desserializar o conteúdo:

var response = await httpClient.GetAsync("https://localhost:12345/teste/site");

if (response.Content.Headers.ContentType?.MediaType == "application/json")
{
  
//desserializar o conteúdo JSON
}
...

O cabeçalho Content.Headers é do tipo HttpContentHeaders. Assim como a classe de cabeçalhos de resposta, ele tem muitas propriedades fortemente tipadas para cabeçalhos comuns (como Content-Type).

No cenário em que você precisa ler cabeçalhos de conteúdo personalizados, pode usar Content.Headers.TryGetValues().

No entanto, se precisar fazer isso, você pode seguir a mesma abordagem mostrada em - Ler cabeçalhos específicos. É a mesma abordagem para cabeçalhos de conteúdo e cabeçalhos de resposta porque ambas as classes são subclasses de HttpHeaders.

E estamos conversados...

"No último dia, o mais importante da festa, Jesus se levantou e disse em alta voz: “Quem tem sede, venha a mim e beba!"
João 7:27

Referências:


José Carlos Macoratti