Manipuladores de Mensagens HttpClient no ASP.NET Web API

Um manipulador de mensagens é uma classe que recebe uma solicitação HTTP e retorna uma resposta HTTP.

Normalmente, uma série de manipuladores de mensagens são encadeados. O primeiro manipulador recebe uma solicitação HTTP, faz algum processamento e fornece a solicitação para o próximo manipulador. Em algum momento, a resposta é criada e faz backup da cadeia. Esse padrão é chamado de manipulador de delegação .

Diagrama de manipuladores de mensagens encadeados, ilustrando o processo para receber uma solicitação H T TP e retornar uma resposta H T TP.

No lado do cliente, a classe HttpClient usa um manipulador de mensagens para processar solicitações. O manipulador padrão é HttpClientHandler, que envia a solicitação pela rede e obtém a resposta do servidor. Você pode inserir manipuladores de mensagens personalizados no pipeline do cliente:

Diagrama do processo para inserir manipuladores de mensagens personalizados no pipeline do cliente. Mostra a classe de cliente h t t p que usa um manipulador de mensagens para processar solicitações.

Observação

ASP.NET Web API também usa manipuladores de mensagens no lado do servidor. Para obter mais informações, consulte Manipuladores de mensagens HTTP.

Manipuladores de Mensagens Personalizadas

Para escrever um manipulador de mensagens personalizado, derive de System.Net.Http.DelegatingHandler e substitua o método SendAsync . Veja a assinatura do método:

Task<HttpResponseMessage> SendAsync(
    HttpRequestMessage request, CancellationToken cancellationToken);

O método usa um HttpRequestMessage como entrada e retorna de forma assíncrona um HttpResponseMessage. Uma implementação típica faz o seguinte:

  1. Processe a mensagem de solicitação.
  2. Chame base.SendAsync para enviar a solicitação para o manipulador interno.
  3. O manipulador interno retorna uma mensagem de resposta. (Esta etapa é assíncrona.)
  4. Processe a resposta e retorne-a ao chamador.

O exemplo a seguir mostra um manipulador de mensagens que adiciona um cabeçalho personalizado à solicitação de saída:

class MessageHandler1 : DelegatingHandler
{
    private int _count = 0;

    protected override Task<HttpResponseMessage> SendAsync(
        HttpRequestMessage request, System.Threading.CancellationToken cancellationToken)
    {
        System.Threading.Interlocked.Increment(ref _count);
        request.Headers.Add("X-Custom-Header", _count.ToString());
        return base.SendAsync(request, cancellationToken);
    }
}

A chamada a base.SendAsync é assíncrona. Se o manipulador fizer qualquer trabalho após essa chamada, use a palavra-chave await para retomar a execução após a conclusão do método. O exemplo a seguir mostra um manipulador que registra códigos de erro. O registro em log em si não é muito interessante, mas o exemplo mostra como obter a resposta dentro do manipulador.

class LoggingHandler : DelegatingHandler
{
    StreamWriter _writer;

    public LoggingHandler(Stream stream)
    {
        _writer = new StreamWriter(stream);
    }

    protected override async Task<HttpResponseMessage> SendAsync(
        HttpRequestMessage request, System.Threading.CancellationToken cancellationToken)
    {
        var response = await base.SendAsync(request, cancellationToken);

        if (!response.IsSuccessStatusCode)
        {
            _writer.WriteLine("{0}\t{1}\t{2}", request.RequestUri, 
                (int)response.StatusCode, response.Headers.Date);
        }
        return response;
    }

    protected override void Dispose(bool disposing)
    {
        if (disposing)
        {
            _writer.Dispose();
        }
        base.Dispose(disposing);
    }
}

Adicionando manipuladores de mensagens ao pipeline do cliente

Para adicionar manipuladores personalizados ao HttpClient, use o método HttpClientFactory.Create :

HttpClient client = HttpClientFactory.Create(new Handler1(), new Handler2(), new Handler3());

Manipuladores de mensagens são chamados na ordem em que você os passa para o método Create . Como os manipuladores estão aninhados, a mensagem de resposta viaja na outra direção. Ou seja, o último manipulador é o primeiro a receber a mensagem de resposta.