Skip to content

Updated HttpClient main topic to address user feedback from issues. #3986

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 15 commits into from
May 20, 2022
Merged
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
112 changes: 82 additions & 30 deletions xml/System.Net.Http/HttpClient.xml
Original file line number Diff line number Diff line change
Expand Up @@ -30,37 +30,10 @@

## Remarks
The <xref:System.Net.Http.HttpClient> class instance acts as a session to send HTTP requests. An <xref:System.Net.Http.HttpClient> instance is a collection of settings applied to all requests executed by that instance. In addition, every <xref:System.Net.Http.HttpClient> instance uses its own connection pool, isolating its requests from requests executed by other <xref:System.Net.Http.HttpClient> instances.

The <xref:System.Net.Http.HttpClient> also acts as a base class for more specific HTTP clients. An example would be a FacebookHttpClient providing additional methods specific to a Facebook web service (a GetFriends method, for instance). Derived classes should not override the virtual methods on the class. Instead, use a constructor overload that accepts <xref:System.Net.Http.HttpMessageHandler> to configure any pre- or post-request processing instead.

By default on .NET Framework and Mono, <xref:System.Net.HttpWebRequest> is used to send requests to the server. This behavior can be modified by specifying a different channel in one of the constructor overloads taking a <xref:System.Net.Http.HttpMessageHandler> instance as parameter. If features like authentication or caching are required, <xref:System.Net.Http.WebRequestHandler> can be used to configure settings and the instance can be passed to the constructor. The returned handler can be passed to one of the constructor overloads taking a <xref:System.Net.Http.HttpMessageHandler> parameter.

If an app using <xref:System.Net.Http.HttpClient> and related classes in the <xref:System.Net.Http> namespace intends to download large amounts of data (50 megabytes or more), then the app should stream those downloads and not use the default buffering. If the default buffering is used the client memory usage will get very large, potentially resulting in substantially reduced performance.

Properties of <xref:System.Net.Http.HttpClient> should not be modified while there are outstanding requests, because it is not thread-safe.
### Instancing


The following methods are thread safe:

1. <xref:System.Net.Http.HttpClient.CancelPendingRequests%2A>

2. <xref:System.Net.Http.HttpClient.DeleteAsync%2A>

3. <xref:System.Net.Http.HttpClient.GetAsync%2A>

4. <xref:System.Net.Http.HttpClient.GetByteArrayAsync%2A>

5. <xref:System.Net.Http.HttpClient.GetStreamAsync%2A>

6. <xref:System.Net.Http.HttpClient.GetStringAsync%2A>

7. <xref:System.Net.Http.HttpClient.PostAsync%2A>

8. <xref:System.Net.Http.HttpClient.PutAsync%2A>

9. <xref:System.Net.Http.HttpClient.SendAsync%2A>

<xref:System.Net.Http.HttpClient> is intended to be instantiated once and re-used throughout the life of an application. Instantiating an HttpClient class for every request will exhaust the number of sockets available under heavy loads. This will result in SocketException errors. Below is an example using HttpClient correctly.
<xref:System.Net.Http.HttpClient> is intended to be instantiated once and re-used throughout the life of an application. HttpClient is designed to pool connections, and re-use a connection across multiple requests. Instantiating an HttpClient class for every request will exhaust the number of sockets available under heavy loads. This will result in SocketException errors. Below is an example using HttpClient correctly.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will result in SocketException errors.

Though they'll be wrapped when actually emerging into user code, right? e.g. in an HttpRequestException?


```csharp
public class GoodController : ApiController
Expand All @@ -85,6 +58,13 @@ public class GoodController : ApiController
End Sub
End Class
```
Additional options can be configured by passing in a <xref:System.Net.Http.HttpClientHandler> (or <xref:System.Net.Http.SocketsHttpHandler> in .NET Core 2.1 or later) as part of the constructor. The connection properties on the handler cannot be changed once a request has been submitted, so one reason to create a new HttpClient instance would be if the connection properties need to be changed.

### Derivation

The <xref:System.Net.Http.HttpClient> also acts as a base class for more specific HTTP clients. An example would be a FacebookHttpClient providing additional methods specific to a Facebook web service (a GetFriends method, for instance). Derived classes should not override the virtual methods on the class. Instead, use a constructor overload that accepts <xref:System.Net.Http.HttpMessageHandler> to configure any pre- or post-request processing instead.

### Transports

The <xref:System.Net.Http.HttpClient> is a high-level API that wraps the lower-level functionality available on each platform where it runs.

Expand All @@ -107,7 +87,11 @@ On each platform, <xref:System.Net.Http.HttpClient> tries to use the best availa

Users can also configure a specific transport for <xref:System.Net.Http.HttpClient> by invoking the <xref:System.Net.Http.HttpClient.%23ctor*> constructor that takes an <xref:System.Net.Http.HttpMessageHandler>.

### HttpClient and .NET Core
#### .NET Framework & Mono

By default on .NET Framework and Mono, <xref:System.Net.HttpWebRequest> is used to send requests to the server. This behavior can be modified by specifying a different channel in one of the constructor overloads taking a <xref:System.Net.Http.HttpMessageHandler> instance as parameter. If features like authentication or caching are required, <xref:System.Net.Http.WebRequestHandler> can be used to configure settings and the instance can be passed to the constructor. The returned handler can be passed to one of the constructor overloads taking a <xref:System.Net.Http.HttpMessageHandler> parameter.

#### .NET Core

Starting with .NET Core 2.1, the <xref:System.Net.Http.SocketsHttpHandler?displayProperty=nameWithType> class instead of `HttpClientHandler` provides the implementation used by higher-level HTTP networking classes such as `HttpClient`. The use of <xref:System.Net.Http.SocketsHttpHandler> offers a number of advantages:

Expand Down Expand Up @@ -140,6 +124,74 @@ If this change is undesirable, you can configure your application to use the old

- By defining an environment variable named `DOTNET_SYSTEM_NET_HTTP_USESOCKETSHTTPHANDLER` and setting it to either `false` or 0.

### Connection Pooling

HttpClient will pool HTTP connections where possible, and use them for more than one request. This can have a significant performance benefit, especially for HTTPS requests, as the connection handshake is only done once.

Connection pool properties can be configured on a <xref:System.Net.Http.HttpClientHandler> or <xref:System.Net.Http.SocketsHttpHandler> passed in during construction, including <xref:System.Net.Http.HttpClientHandler.MaxConnectionsPerServer>, <xref:System.Net.Http.SocketsHttpHandler.PooledConnectionIdleTimeout> and <xref:System.Net.Http.SocketsHttpHandler.PooledConnectionLifetime>.

Todo: Disposing of the HttpClient instance will close the open connections and cancel any pending requests.

### Buffering & Request lifetime

By default, HttpClient methods (except <xref:System.Net.Http.HttpClient.GetStreamAsync>) will buffer the responses from the server, reading all the response body into memory before returning the async result. Those requests will continue until one of the following occurs:

* The <xref:System.Threading.Tasks.Task%601> succeds and returns a result
* The <xref:System.Net.Http.HttpClient.Timeout> is reached, in which case the <xref:System.Threading.Tasks.Task%601> will be cancelled
* The <xref:System.Threading.CancellationToken> passable to some method overloads is fired
* <xref:System.Net.Http.HttpClient.CancelPendingRequests> is called
* The HttpClient is disposed

The buffering behavior can be changed on a per request basis using the HttpCompletionOption parameter available on some method overloads. This can be used to specify if the <xref:System.Threading.Tasks.Task%601> should be considered complete after reading just the response headers, or having read and buffered the response content.

If an app using <xref:System.Net.Http.HttpClient> and related classes in the <xref:System.Net.Http> namespace intends to download large amounts of data (50 megabytes or more), then the app should stream those downloads and not use the default buffering. If the default buffering is used the client memory usage will get very large, potentially resulting in substantially reduced performance.

### Thread Safety

The following methods are thread safe:

1. <xref:System.Net.Http.HttpClient.CancelPendingRequests%2A>

2. <xref:System.Net.Http.HttpClient.DeleteAsync%2A>

3. <xref:System.Net.Http.HttpClient.GetAsync%2A>

4. <xref:System.Net.Http.HttpClient.GetByteArrayAsync%2A>

5. <xref:System.Net.Http.HttpClient.GetStreamAsync%2A>

6. <xref:System.Net.Http.HttpClient.GetStringAsync%2A>

7. <xref:System.Net.Http.HttpClient.PostAsync%2A>

8. <xref:System.Net.Http.HttpClient.PutAsync%2A>

9. <xref:System.Net.Http.HttpClient.SendAsync%2A>

### Proxies

By deafult HttpClient will read proxy configuration from environment variables or user / system settings depending on the platform being used. This can be changed by passing a <xref:System.Net.WebProxy> or <xref:System.Net.IWebProxy> to, in order of precedence:

* The <xref:System.Net.Http.HttpClientHandler.Proxy> property on a HttpClientHandler passed in during HttpClient construction
* The <xref:System.Net.http.HttpClient.DefaultProxy> static property (affects all instanes)

The proxy can be disabled using <xref:System.Net.Http.HttpClientHandler.UseProxy>. The default configuration for Windows users is to try and detect a proxy using network discovery which can be slow. For high througput applications where its known that a proxy is not required, the proxy should be disabled.

### Timeouts

HttpClient.Timeout can be used to set a default timeout for all Http requests from the HttpClient instance. The timeout only applies to the xxxAsync methods that cause a request/response to be initiated. If the timeout is reached, the <xref:System.Threading.Tasks.Task%601> for that request will be cancelled.

Some Additional timeouts can be set if you construct the HttpClient passing in a <xref:System.Net.Http.SocketsHttpHandler> instance:

| **Property** | **Description**|
| ------------ | -------------- |
| <xref:System.Net.Http.SocketsHttpHandler.ConnectTimeout> | Specifies a timeout that is used when a request requires a new TCP connection to be created. If the timout occurs the request <xref:System.Threading.Tasks.Task%601> is cancelled. |
| <xref:System.Net.Http.SocketsHttpHandler.PooledConnectionLifetime> | Specifies a timeout to be used for each connection in the connection pool. If the connection is idle, it is immediately closed, otherwise at the end of the current request. |
| <xref:System.Net.Http.SocketsHttpHandler.PooledConnectionIdleTimeout> | If a connection in the connection pool is idle for this long the connection will be closed. |
| <xref:System.Net.Http.SocketsHttpHandler.Expect100ContinueTimeout> | If request has an "Expect: 100-continue" header, it will delay sending the body until the timeout or a "100-continue" response has been recieved. |

HttpClient will only resolve DNS entries when the connections are created, it does not track any TTL durations specified by the DNS server. If DNS entries are changing regularly, which can happen in some container scenarios, the <xref:System.Net.Http.SocketsHttpHandler.PooledConnectionLifetime> can be used to limit the lifetime of the connection so that DNS will be requiried when replacing the connection.

## Examples
[!code-csharp[System.Net.Http.HttpClient#1](~/samples/snippets/csharp/VS_Snippets_Misc/system.net.http.httpclient/cs/source.cs#1)]
[!code-vb[System.Net.Http.HttpClient#1](~/samples/snippets/visualbasic/VS_Snippets_Misc/system.net.http.httpclient/vb/source.vb#1)]
Expand Down