System.Net.Http.HttpClient classe

Este artigo fornece observações complementares à documentação de referência para essa API.

A HttpClient instância de classe atua como uma sessão para enviar solicitações HTTP. Uma HttpClient instância é uma coleção de configurações aplicadas a todas as solicitações executadas por essa instância. Além disso, cada HttpClient instância usa seu próprio pool de conexões, isolando suas solicitações das solicitações executadas por outras HttpClient instâncias.

Instanciação

HttpClient destina-se a ser instanciado uma vez e reutilizado durante toda a vida útil de um aplicativo. No .NET Core e no .NET 5+, o HttpClient agrupa conexões dentro da instância do manipulador e reutiliza uma conexão em várias solicitações. Se você instanciar uma classe HttpClient para cada solicitação, o número de soquetes disponíveis sob cargas pesadas será esgotado. Essa exaustão resultará em SocketException erros.

Você pode configurar opções adicionais passando um "manipulador", como HttpClientHandler (ou SocketsHttpHandler no .NET Core 2.1 ou posterior), como parte do construtor. As propriedades de conexão no manipulador não podem ser alteradas depois que uma solicitação é enviada, portanto, um motivo para criar uma nova instância HttpClient seria se você precisar alterar as propriedades de conexão. Se solicitações diferentes exigirem configurações diferentes, isso também pode levar a um aplicativo com várias HttpClient instâncias, onde cada instância é configurada adequadamente e, em seguida, as solicitações são emitidas no cliente relevante.

HttpClient só resolve entradas DNS quando uma conexão é criada. Ele não controla as durações do TTL (tempo de vida útil) especificadas pelo servidor DNS. Se as entradas DNS forem alteradas regularmente, o que pode acontecer em alguns cenários de contêiner, o cliente não respeitará essas atualizações. Para resolver esse problema, você pode limitar o tempo de vida da conexão definindo a propriedade SocketsHttpHandler.PooledConnectionLifetime, de modo que a pesquisa DNS seja necessária quando a conexão for substituída.

public class GoodController : ApiController
{
    private static readonly HttpClient httpClient;

    static GoodController()
    {
        var socketsHandler = new SocketsHttpHandler
        {
            PooledConnectionLifetime = TimeSpan.FromMinutes(2)
        };

        httpClient = new HttpClient(socketsHandler);
    }
}

Como alternativa à criação de apenas uma instância HttpClient, você também pode usar IHttpClientFactory para gerenciar as instâncias HttpClient para você. Para obter mais informações, confira Diretrizes para usar HttpClient.

Derivação

O HttpClient também atua como uma classe base para clientes HTTP mais específicos. Um exemplo seria um FacebookHttpClient que fornece métodos adicionais específicos para um serviço Web do Facebook (por exemplo, um GetFriends método). As classes derivadas não devem substituir os métodos virtuais na classe. Em vez disso, use uma sobrecarga de construtor que aceite HttpMessageHandler configurar qualquer processamento pré-solicitação ou pós-solicitação.

Transportes

O HttpClient é uma API de alto nível que envolve a funcionalidade de nível inferior disponível em cada plataforma em que é executado.

Em cada plataforma, HttpClient tente utilizar o melhor transporte disponível:

Host/Tempo de execução Back-end
Windows/.NET Framework HttpWebRequest
Windows/Mono HttpWebRequest
Windows/UWP Nativo WinHttpHandler do Windows (compatível com HTTP 2.0)
Windows/.NET Core 1.0-2.0 Nativo WinHttpHandler do Windows (compatível com HTTP 2.0)
Android/Xamarin Selecionado em tempo de compilação. Pode usar HttpWebRequest ou ser configurado para usar o nativo do Android HttpURLConnection
iOS, tvOS, watchOS/Xamarin Selecionado em tempo de compilação. Pode usar HttpWebRequest ou ser configurado para usar o NSUrlSession da Apple (compatível com HTTP 2.0)
macOS/Xamarin Selecionado em tempo de compilação. Pode usar HttpWebRequest ou ser configurado para usar o NSUrlSession da Apple (compatível com HTTP 2.0)
macOS/Mono HttpWebRequest
macOS/.NET Core 1.0-2.0 libcurltransporte HTTP baseado em HTTP (compatível com HTTP 2.0)
Linux/Mono HttpWebRequest
Linux/.NET Core 1.0-2.0 libcurltransporte HTTP baseado em HTTP (compatível com HTTP 2.0)
.NET Core 2.1 e posteriores System.Net.Http.SocketsHttpHandler

Os usuários também podem configurar um transporte específico para HttpClient invocando o HttpClient construtor que usa um HttpMessageHandlerarquivo .

.NET Framework & Mono

Por padrão, no .NET Framework e Mono, HttpWebRequest é usado para enviar solicitações para o servidor. Esse comportamento pode ser modificado especificando um manipulador diferente em uma das sobrecargas do construtor com um HttpMessageHandler parâmetro. Se você precisar de recursos como autenticação ou cache, poderá usar WebRequestHandler para definir as configurações e a instância poderá ser passada para o construtor. O manipulador retornado pode ser passado para uma sobrecarga do construtor que tem um HttpMessageHandler parâmetro.

.NET Core

A partir do .NET Core 2.1, a System.Net.Http.SocketsHttpHandler classe em vez de fornece a implementação usada por classes de HttpClientHandler rede HTTP de nível superior, como HttpClient. O uso de SocketsHttpHandler oferece uma série de vantagens:

  • Uma melhoria de desempenho significativa quando comparada com a implementação anterior.
  • A eliminação das dependências da plataforma, o que simplifica a implantação e a manutenção. Por exemplo, libcurl não é mais uma dependência do .NET Core para macOS e do .NET Core para Linux.
  • Comportamento consistente em todas as plataformas .NET.

Se essa alteração for indesejável, no Windows você pode continuar a usar WinHttpHandler referenciando seu pacote NuGet e passando-o para o construtor do HttpClient manualmente.

Configurar o comportamento usando opções de configuração de tempo de execução

Certos aspectos do comportamento do são personalizáveis por meio das opções de configuração do HttpClientRuntime. No entanto, o comportamento dessas opções difere por meio de versões do .NET. Por exemplo, no .NET Core 2.1 - 3.1, você pode configurar se SocketsHttpHandler é usado por padrão, mas essa opção não está mais disponível a partir do .NET 5.

Pool de conexões

HttpClient agrupa conexões HTTP sempre que possível e as usa para mais de uma solicitação. Isso pode ter um benefício significativo de desempenho, especialmente para solicitações HTTPS, já que o handshake de conexão é feito apenas uma vez.

As propriedades do pool de conexões podem ser configuradas em um ou passadas durante a HttpClientHandler construção, incluindo MaxConnectionsPerServer, PooledConnectionIdleTimeoute PooledConnectionLifetime.SocketsHttpHandler

O descarte da instância HttpClient fecha as conexões abertas e cancela todas as solicitações pendentes.

Observação

Se você enviar simultaneamente solicitações HTTP/1.1 para o mesmo servidor, novas conexões poderão ser criadas. Mesmo se você reutilizar a HttpClient instância, se a taxa de solicitações for alta ou se houver alguma limitação de firewall, isso pode esgotar os soquetes disponíveis devido aos temporizadores de limpeza TCP padrão. Para limitar o número de conexões simultâneas, você pode definir a MaxConnectionsPerServer propriedade. Por padrão, o número de conexões HTTP/1.1 simultâneas é ilimitado.

Armazenamento em buffer e tempo de vida da solicitação

Por padrão, os métodos HttpClient (exceto GetStreamAsync) armazenam em buffer as respostas do servidor, lendo todo o corpo da resposta na memória antes de retornar o resultado assíncrono. Essas solicitações continuarão até que ocorra uma das seguintes situações:

Você pode alterar o comportamento de buffer por solicitação usando o HttpCompletionOption parâmetro disponível em algumas sobrecargas de método. Esse argumento pode ser usado para especificar se o deve ser considerado completo depois de Task<TResult> ler apenas os cabeçalhos de resposta ou depois de ler e armazenar em buffer o conteúdo da resposta.

Se seu aplicativo que usa HttpClient classes relacionadas no System.Net.Http namespace pretende baixar grandes quantidades de dados (50 megabytes ou mais), o aplicativo deve transmitir esses downloads e não usar o buffer padrão. Se você usar o buffer padrão, o uso de memória do cliente ficará muito grande, potencialmente resultando em desempenho substancialmente reduzido.

Acesso thread-safe

Os seguintes métodos são thread safe:

Proxies

Por padrão, o HttpClient lê a configuração de proxy a partir de variáveis de ambiente ou configurações de usuário/sistema, dependendo da plataforma. Você pode alterar esse comportamento passando um WebProxy ou IWebProxy para, em ordem de precedência:

  • A Proxy propriedade em um HttpClientHandler passou durante a construção de HttpClient
  • A DefaultProxy propriedade static (afeta todas as instâncias)

Você pode desabilitar o proxy usando UseProxyo . A configuração padrão para usuários do Windows é tentar detectar um proxy usando a descoberta de rede, que pode ser lenta. Para aplicativos de alta taxa de transferência em que se sabe que um proxy não é necessário, você deve desabilitar o proxy.

As configurações de proxy (como Credentials) devem ser alteradas somente antes que a primeira solicitação seja feita usando o HttpClient. As alterações feitas após o uso do HttpClient pela primeira vez podem não ser refletidas em solicitações subsequentes.

Tempos limite

Você pode usar Timeout para definir um tempo limite padrão para todas as solicitações HTTP da instância HttpClient. O tempo limite só se aplica aos métodos xxxAsync que fazem com que uma solicitação/resposta seja iniciada. Se o tempo limite for atingido, a Task<TResult> solicitação será cancelada.

Você pode definir alguns tempos limite adicionais se passar em uma SocketsHttpHandler instância ao construir o objeto HttpClient:

Propriedade Descrição
ConnectTimeout Especifica um tempo limite usado quando uma solicitação requer a criação de uma nova conexão TCP. Se o tempo limite ocorrer, a solicitação Task<TResult> será cancelada.
PooledConnectionLifetime Especifica um tempo limite a ser usado para cada conexão no pool de conexões. Se a conexão estiver ociosa, a conexão é imediatamente fechada; caso contrário, a conexão será fechada no final da solicitação atual.
PooledConnectionIdleTimeout Se uma conexão no pool de conexões ficar ociosa por esse tempo, a conexão será fechada.
Expect100ContinueTimeout Se a solicitação tiver um cabeçalho "Esperar: 100-continuar", ela atrasará o envio de conteúdo até o tempo limite ou até que uma resposta "100-continue" seja recebida.

HttpClient só resolve entradas DNS quando as conexões são criadas. Ele não controla as durações do TTL (tempo de vida útil) especificadas pelo servidor DNS. Se as entradas DNS estiverem sendo alteradas regularmente, o que pode acontecer em alguns cenários de contêiner, você poderá usar o PooledConnectionLifetime para limitar o tempo de vida da conexão para que a pesquisa de DNS seja necessária ao substituir a conexão.