Condividi tramite


Classe System.Net.Http.HttpClient

Questo articolo fornisce osservazioni supplementari alla documentazione di riferimento per questa API.

L'istanza della HttpClient classe funge da sessione per inviare richieste HTTP. Un'istanza HttpClient è una raccolta di impostazioni applicate a tutte le richieste eseguite da tale istanza. Inoltre, ogni HttpClient istanza usa il proprio pool di connessioni, isolando le richieste dalle richieste eseguite da altre HttpClient istanze.

Istanze

HttpClient deve essere istanziato una sola volta e riutilizzato per tutta la durata di un'applicazione. In .NET Core e .NET 5+, HttpClient raccoglie le connessioni all'interno dell'istanza del gestore delle richieste e riutilizza una connessione per più richieste. Se si istanzia una classe HttpClient per ogni richiesta, il numero di socket disponibili sotto carichi pesanti si esaurirà. Questo esaurimento genererà SocketException errori.

È possibile configurare opzioni aggiuntive passando un "gestore", ad esempio HttpClientHandler (o SocketsHttpHandler in .NET Core 2.1 o versione successiva), come parte del costruttore. Le proprietà di connessione nel gestore non possono essere modificate dopo l'invio di una richiesta, quindi un motivo per creare una nuova istanza HttpClient sarebbe se fosse necessario modificare le proprietà di connessione. Se richieste diverse richiedono impostazioni diverse, questo può comportare anche la presenza di più HttpClient istanze di un'applicazione, in cui ogni istanza è configurata in modo appropriato e quindi le richieste vengono inviate nel client pertinente.

HttpClient risolve solo le voci DNS quando viene creata una connessione. Non tiene traccia del tempo di vita (TTL) delle durate specificate dal server DNS. Se le voci DNS cambiano regolarmente, che possono verificarsi in alcuni scenari di contenitore, il client non rispetterà tali aggiornamenti. Per risolvere questo problema, è possibile limitare la durata della connessione impostando la SocketsHttpHandler.PooledConnectionLifetime proprietà , in modo che la ricerca DNS sia necessaria quando la connessione viene sostituita.

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

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

        httpClient = new HttpClient(socketsHandler);
    }
}

In alternativa alla creazione di una sola istanza HttpClient, è anche possibile usare IHttpClientFactory per gestire le istanze HttpClient. Per ricevere ulteriori informazioni, consultare l'articolo Linee guida per l'uso di HttpClient.

Derivazione

Funge HttpClient anche da classe di base per client HTTP più specifici. Un esempio è un FacebookHttpClient che fornisce metodi aggiuntivi specifici di un servizio Web Facebook (ad esempio, un GetFriends metodo). Le classi derivate non devono eseguire l'override dei metodi virtuali nella classe . Invece, usa un overload del costruttore che accetta HttpMessageHandler per configurare qualunque elaborazione pre-richiesta o post-richiesta.

Trasporti

è un'API HttpClient di alto livello che esegue il wrapping delle funzionalità di livello inferiore disponibili in ogni piattaforma in cui viene eseguita.

In ogni piattaforma tenta HttpClient di usare il trasporto migliore disponibile:

Host/Runtime back-end
Windows/.NET Framework HttpWebRequest
Windows/Mono HttpWebRequest
Windows/UWP Windows nativo WinHttpHandler (compatibile con HTTP 2.0)
Windows/.NET Core 1.0-2.0 Windows nativo WinHttpHandler (compatibile con HTTP 2.0)
macOS/Mono HttpWebRequest
macOS/.NET Core 1.0-2.0 libcurlTrasporto HTTP basato su libcurl (compatibile con HTTP/2)
Linux/Mono HttpWebRequest
Linux/.NET Core 1.0-2.0 libcurlTrasporto HTTP basato su libcurl (compatibile con HTTP/2)
.NET Core 2.1 e versioni successive System.Net.Http.SocketsHttpHandler

Gli utenti possono anche configurare un trasporto specifico per HttpClient richiamando il HttpClient costruttore che accetta un oggetto HttpMessageHandler.

.NET Framework & Mono

Per impostazione predefinita, in .NET Framework e Mono viene HttpWebRequest usato per inviare richieste al server. Questo comportamento può essere modificato specificando un gestore diverso in uno degli overload del costruttore con un HttpMessageHandler parametro . Se sono necessarie funzionalità come l'autenticazione o la memorizzazione nella cache, è possibile usare WebRequestHandler per configurare le impostazioni e l'istanza può essere passata al costruttore. Il gestore restituito può essere passato a un overload del costruttore con un parametro HttpMessageHandler.

.NET Core

A partire da .NET Core 2.1, la classe System.Net.Http.SocketsHttpHandler anziché HttpClientHandler fornisce l'implementazione utilizzata dalle classi HTTP di livello superiore come HttpClient. L'uso di SocketsHttpHandler offre numerosi vantaggi:

  • Miglioramento significativo delle prestazioni rispetto all'implementazione precedente.
  • Eliminazione delle dipendenze della piattaforma, che semplifica la distribuzione e la manutenzione. Ad esempio, libcurl non è più una dipendenza da .NET Core per macOS e .NET Core per Linux.
  • Comportamento coerente in tutte le piattaforme .NET.

Se questa modifica è indesiderata, in Windows è possibile continuare a usare WinHttpHandler facendo riferimento al pacchetto NuGet e passandolo manualmente al costruttore di HttpClient .

Configurare il comportamento usando le opzioni di configurazione di runtime

Alcuni aspetti del HttpClientcomportamento sono personalizzabili tramite le opzioni di configurazione di runtime. Tuttavia, il comportamento di questi interruttori differisce attraverso le versioni di .NET. Ad esempio, in .NET Core 2.1 - 3.1 è possibile configurare se SocketsHttpHandler viene usato per impostazione predefinita, ma tale opzione non è più disponibile a partire da .NET 5.

Pool di connessioni

HttpClient raggruppa connessioni HTTP laddove possibile e le usa per più di una richiesta. Ciò può avere un vantaggio significativo in termini di prestazioni, soprattutto per le richieste HTTPS, perché l'handshake di connessione viene eseguito una sola volta.

Le proprietà del pool di connessioni possono essere configurate su un oggetto HttpClientHandler o SocketsHttpHandler passate durante la costruzione, tra cui MaxConnectionsPerServer, PooledConnectionIdleTimeout, e PooledConnectionLifetime.

L'eliminazione dell'istanza HttpClient chiude le connessioni aperte e annulla le richieste in sospeso.

Annotazioni

Se si inviano simultaneamente richieste HTTP/1.1 allo stesso server, è possibile creare nuove connessioni. Anche se si riutilizza l'istanza HttpClient , se la frequenza delle richieste è elevata o se sono presenti limitazioni del firewall, è possibile esaurire i socket disponibili a causa dei timer di pulizia TCP predefiniti. Per limitare il numero di connessioni simultanee, è possibile impostare la MaxConnectionsPerServer proprietà . Per impostazione predefinita, il numero di connessioni HTTP/1.1 simultanee è illimitato.

Memorizzazione nel buffer e durata delle richieste

Per impostazione predefinita, i metodi HttpClient (ad eccezione GetStreamAsyncdi ) memorizzano nel buffer le risposte dal server, leggendo tutto il corpo della risposta in memoria prima di restituire il risultato asincrono. Tali richieste continueranno fino a quando non si verifica una delle seguenti operazioni:

È possibile modificare il comportamento di buffering per ogni richiesta usando il parametro HttpCompletionOption disponibile in alcuni overload del metodo. Questo argomento può essere usato per specificare se il Task<TResult> debba essere considerato completo dopo aver letto solo le intestazioni della risposta o dopo aver letto e memorizzato in memoria temporanea il contenuto della risposta.

Se l'app che usa HttpClient e classi correlate nello System.Net.Http spazio dei nomi intende scaricare grandi quantità di dati (50 megabyte o più), l'app deve trasmettere tali download e non usare il buffer predefinito. Se si usa il buffering predefinito, l'utilizzo della memoria client avrà dimensioni molto elevate, con conseguente riduzione sostanziale delle prestazioni.

Sicurezza dei thread

I metodi seguenti sono thread-safe:

Proxy

Per impostazione predefinita, HttpClient legge la configurazione proxy dalle variabili di ambiente o dalle impostazioni utente/sistema, a seconda della piattaforma. È possibile modificare questo comportamento passando un WebProxy o un IWebProxy, in ordine di precedenza:

  • Proprietà Proxy in un HttpClientHandler passato durante la costruzione di HttpClient
  • La DefaultProxy proprietà statica (influisce su tutte le istanze)

È possibile disabilitare il proxy usando UseProxy. La configurazione predefinita per gli utenti di Windows consiste nel provare a rilevare un proxy usando l'individuazione di rete, che può essere lento. Per le applicazioni a velocità effettiva elevata in cui è noto che un proxy non è necessario, è consigliabile disabilitare il proxy.

Le impostazioni proxy (ad esempio Credentials) devono essere modificate solo prima che venga effettuata la prima richiesta usando HttpClient. Le modifiche apportate dopo l'uso di HttpClient per la prima volta potrebbero non essere riflesse nelle richieste successive.

Timeout

È possibile usare Timeout per impostare un timeout predefinito per tutte le richieste HTTP dall'istanza HttpClient. Il timeout si applica solo ai metodi xxxAsync che causano l'avvio di una richiesta/risposta. Se il timeout viene raggiunto, l'oggetto Task<TResult> relativo a quella richiesta viene annullato.

È possibile impostare alcuni timeout aggiuntivi se si passa un'istanza SocketsHttpHandler quando si costruisce l'oggetto HttpClient:

Proprietà Descrizione
ConnectTimeout Specifica un timeout utilizzato quando una richiesta richiede la creazione di una nuova connessione TCP. Se si verifica il timeout, la richiesta Task<TResult> viene annullata.
PooledConnectionLifetime Specifica un timeout da utilizzare per ogni connessione nel pool di connessioni. Se la connessione è inattiva, la connessione viene chiusa immediatamente; in caso contrario, la connessione viene chiusa alla fine della richiesta corrente.
PooledConnectionIdleTimeout Se una connessione nel pool di connessioni è inattiva per questo lungo periodo, la connessione viene chiusa.
Expect100ContinueTimeout Se la richiesta ha un'intestazione "Expect: 100-continue", ritarda l'invio del contenuto fino al timeout o fino alla ricezione di una risposta "100-continue".

HttpClient risolve solo le voci DNS quando vengono create le connessioni. Non tiene traccia del tempo di vita (TTL) delle durate specificate dal server DNS. Se le voci DNS cambiano regolarmente, che possono verificarsi in alcuni scenari di contenitore, è possibile usare PooledConnectionLifetime per limitare la durata della connessione in modo che la ricerca DNS sia necessaria quando si sostituisce la connessione.