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 all 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
121 changes: 83 additions & 38 deletions xml/System.Net.Http/HttpClient.xml
Original file line number Diff line number Diff line change
Expand Up @@ -36,41 +36,13 @@
<remarks>
<format type="text/markdown"><![CDATA[

## 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.

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.

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.
## Remarks

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

10. <xref:System.Net.Http.HttpClient.PatchAsync%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 reused throughout the life of an application. HttpClient is designed to pool connections and reuse a connection across multiple requests. If you instantiate an HttpClient class for every request, the number of sockets available under heavy loads will be exhausted. This exhaustion will result in <xref:System.Net.Sockets.SocketException> errors. Following is an example that uses HttpClient correctly.

```csharp
public class GoodController : ApiController
Expand Down Expand Up @@ -101,6 +73,13 @@ type GoodController() =
End Sub
End Class
```
You can configure additional options by passing in a "handler", such as <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 you need to change the connection properties. If different requests require different settings, this may also lead to an application having multiple <xref:System.Net.Http.HttpClient> instances, where each instance is configured appropriately, and then requests are issued on the relevant client.

### Derivation

The <xref:System.Net.Http.HttpClient> also acts as a base class for more specific HTTP clients. An example would be a FacebookHttpClient that provides additional methods specific to a Facebook web service (for example, a `GetFriends` method). 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-request or post-request processing.

### 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 @@ -123,17 +102,83 @@ 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
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:
#### .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 handler in one of the constructor overloads with an <xref:System.Net.Http.HttpMessageHandler> parameter. If you require features like authentication or caching, you can use <xref:System.Net.Http.WebRequestHandler> to configure settings and the instance can be passed to the constructor. The returned handler can be passed to a constructor overload that has an <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 <xref:System.Net.Http.HttpClientHandler> provides the implementation used by higher-level HTTP networking classes such as <xref:System.Net.Http.HttpClient>. The use of <xref:System.Net.Http.SocketsHttpHandler> offers a number of advantages:

- A significant performance improvement when compared with the previous implementation.
- The elimination of platform dependencies, which simplifies deployment and servicing. For example, `libcurl` is no longer a dependency on .NET Core for macOS and .NET Core for Linux.
- Consistent behavior across all .NET platforms.

If this change is undesirable, on Windows you can still use <xref:System.Net.Http.WinHttpHandler> by referencing it's [NuGet package](https://www.nuget.org/packages/System.Net.Http.WinHttpHandler/) and passing it to [`HttpClient`'s constructor](xref:System.Net.Http.HttpClient.%23ctor(System.Net.Http.HttpMessageHandler)) manually.
If this change is undesirable, on Windows you can continue to use <xref:System.Net.Http.WinHttpHandler> by referencing its [NuGet package](https://www.nuget.org/packages/System.Net.Http.WinHttpHandler/) and passing it to [HttpClient's constructor](xref:System.Net.Http.HttpClient.%23ctor(System.Net.Http.HttpMessageHandler)) manually.

### Configure behavior using runtime configuration options

Certain aspects of <xref:System.Net.Http.HttpClient>'s behavior are customizable through [Runtime configuration options](/dotnet/core/run-time-config/networking). However, the behavior of these switches differs through .NET versions. For example, in .NET Core 2.1 - 3.1, you can configure whether <xref:System.Net.Http.SocketsHttpHandler> is used by default, but that option is no longer available starting in .NET 5.0.

### Connection pooling

HttpClient pools HTTP connections where possible and uses 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>.

Disposing of the HttpClient instance closes the open connections and cancels any pending requests.

### Buffering and request lifetime

By default, HttpClient methods (except <xref:System.Net.Http.HttpClient.GetStreamAsync%2A>) 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> succeeds 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.

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

If your app that uses <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 you use the default buffering, the client memory usage will get very large, potentially resulting in substantially reduced performance.

### Thread safety

The following methods are thread safe:

- <xref:System.Net.Http.HttpClient.CancelPendingRequests%2A>
- <xref:System.Net.Http.HttpClient.DeleteAsync%2A>
- <xref:System.Net.Http.HttpClient.GetAsync%2A>
- <xref:System.Net.Http.HttpClient.GetByteArrayAsync%2A>
- <xref:System.Net.Http.HttpClient.GetStreamAsync%2A>
- <xref:System.Net.Http.HttpClient.GetStringAsync%2A>
- <xref:System.Net.Http.HttpClient.PostAsync%2A>
- <xref:System.Net.Http.HttpClient.PutAsync%2A>
- <xref:System.Net.Http.HttpClient.SendAsync%2A>

### Proxies

By default, HttpClient reads proxy configuration from environment variables or user/system settings, depending on the platform. You can change this behavior 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 instances)

You can disable the proxy 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 throughput applications where it's known that a proxy isn't required, you should disable the proxy.

### Timeouts

You can use <xref:System.Net.Http.HttpClient.Timeout> 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 is cancelled.

You can set some additional timeouts if you pass in a <xref:System.Net.Http.SocketsHttpHandler> instance when constructing the HttpClient object:

### Configure behavior using run-time configuration options
| **Property** | **Description**|
| ------------ | -------------- |
| <xref:System.Net.Http.SocketsHttpHandler.ConnectTimeout> | Specifies a timeout that's used when a request requires a new TCP connection to be created. If the timeout 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, the connection is immediately closed; otherwise, the connection is closed 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 is closed. |
| <xref:System.Net.Http.SocketsHttpHandler.Expect100ContinueTimeout> | If request has an "Expect: 100-continue" header, it delays sending content until the timeout or until a "100-continue" response is received. |

Certain aspects of <xref:System.Net.Http.HttpClient>'s behavior are customizable through [Run-time configuration options](/dotnet/core/run-time-config/networking). However, the behavior of these switches differs through .NET versions. For example, in .NET Core 2.1 - 3.1, you can configure whether <xref:System.Net.Http.SocketsHttpHandler> is used by default, but that option is no longer available starting in .NET 5.
HttpClient only resolves DNS entries when the connections are created. It does not track any time to live (TTL) durations specified by the DNS server. If DNS entries are changing regularly, which can happen in some container scenarios, you can use the <xref:System.Net.Http.SocketsHttpHandler.PooledConnectionLifetime> to limit the lifetime of the connection so that DNS lookup is required when replacing the connection.

## Examples
:::code language="csharp" source="~/snippets/csharp/System.Net.Http/HttpClient/source.cs" id="Snippet1":::
Expand Down Expand Up @@ -481,7 +526,7 @@ The proxy server may be a hostname or IP address, optionally followed by a colon
<format type="text/markdown"><![CDATA[

## Remarks
Headers set on this property don't need to be set on request messages again. `DefaultRequestHeaders` should not be modified while there are outstanding requests, because it is not thread-safe.
Headers set on this property don't need to be set on request messages again. `DefaultRequestHeaders` should not be modified while there are outstanding requests.

]]></format>
</remarks>
Expand Down