diff --git a/.github/wordlist.txt b/.github/wordlist.txt
index fe5f2dacbd8..d199af4bbdd 100644
--- a/.github/wordlist.txt
+++ b/.github/wordlist.txt
@@ -12,6 +12,7 @@ circuitbreaker
comparer
contrib
deserialization
+dependencyinjection
dotnet
dotnetrocks
durations
@@ -21,6 +22,8 @@ extensibility
flurl
fs
hangfire
+httpclient
+httpclientfactory
interop
jetbrains
jitter
@@ -50,6 +53,7 @@ rebase
rebased
rebasing
resharper
+restsharp
rethrow
rethrows
retryable
@@ -73,6 +77,7 @@ ui
unhandled
uwp
valuetask
+vnext
waitandretry
wpf
xunit
diff --git a/Directory.Packages.props b/Directory.Packages.props
index c570377cf69..f335137a768 100644
--- a/Directory.Packages.props
+++ b/Directory.Packages.props
@@ -11,6 +11,7 @@
+
@@ -37,7 +38,9 @@
+
+
diff --git a/docs/community/http-client-integrations.md b/docs/community/http-client-integrations.md
new file mode 100644
index 00000000000..57843f628cc
--- /dev/null
+++ b/docs/community/http-client-integrations.md
@@ -0,0 +1,203 @@
+# HTTP client integration samples
+
+Transient failures are inevitable for HTTP based communication as well. It is not a surprise that many developers use Polly with an HTTP client to make there applications more robust.
+
+Here we have collected some popular HTTP client libraries and show how to integrate them with Polly.
+
+## Setting the stage
+
+In the examples below we will register HTTP clients into a Dependency Injection container.
+
+The same resilience strategy will be used each time to keep the samples focused on the HTTP client library integration.
+
+
+```cs
+private static ValueTask HandleTransientHttpError(Outcome outcome) =>
+outcome switch
+{
+ { Exception: HttpRequestException } => PredicateResult.True(),
+ { Result.StatusCode: HttpStatusCode.RequestTimeout } => PredicateResult.True(),
+ { Result.StatusCode: >= HttpStatusCode.InternalServerError } => PredicateResult.True(),
+ _ => PredicateResult.False()
+};
+
+private static RetryStrategyOptions GetRetryOptions() =>
+new()
+{
+ ShouldHandle = args => HandleTransientHttpError(args.Outcome),
+ MaxRetryAttempts = 3,
+ BackoffType = DelayBackoffType.Exponential,
+ Delay = TimeSpan.FromSeconds(2)
+};
+```
+
+
+Here we create a strategy which will retry the HTTP request if the status code is either `408`, greater than or equal to `500`, or an `HttpRequestException` is thrown.
+
+The `HandleTransientHttpError` method is equivalent to the [`HttpPolicyExtensions.HandleTransientHttpError`](https://github.com/App-vNext/Polly.Extensions.Http/blob/93b91c4359f436bda37f870c4453f25555b9bfd8/src/Polly.Extensions.Http/HttpPolicyExtensions.cs) method in the [App-vNext/Polly.Extensions.Http](https://github.com/App-vNext/Polly.Extensions.Http) repository.
+
+## With HttpClient
+
+We use the [`AddResilienceHandler`](https://learn.microsoft.com/dotnet/api/microsoft.extensions.dependencyinjection.resiliencehttpclientbuilderextensions.addresiliencehandler) method to register our resilience strategy with the built-in [`HttpClient`](https://learn.microsoft.com/dotnet/api/system.net.http.httpclient).
+
+
+```cs
+var services = new ServiceCollection();
+
+// Register a named HttpClient and decorate with a resilience pipeline
+services.AddHttpClient(HttpClientName)
+ .ConfigureHttpClient(client => client.BaseAddress = BaseAddress)
+ .AddResilienceHandler("httpclient_based_pipeline",
+ builder => builder.AddRetry(GetRetryOptions()));
+
+using var provider = services.BuildServiceProvider();
+
+// Resolve the named HttpClient
+var httpClientFactory = provider.GetRequiredService();
+var httpClient = httpClientFactory.CreateClient(HttpClientName);
+
+// Use the HttpClient by making a request
+var response = await httpClient.GetAsync("/408");
+```
+
+
+> [!NOTE]
+> The following packages are required to the above example:
+>
+> - [Microsoft.Extensions.DependencyInjection](https://www.nuget.org/packages/microsoft.extensions.dependencyinjection): Required for the dependency injection functionality
+> - [Microsoft.Extensions.Http.Resilience](https://www.nuget.org/packages/Microsoft.Extensions.Http.Resilience): Required for the `AddResilienceHandler` extension
+
+### Further reading for HttpClient
+
+- [Build resilient HTTP apps: Key development patterns](https://learn.microsoft.com/dotnet/core/resilience/http-resilience)
+- [Building resilient cloud services with .NET 8](https://devblogs.microsoft.com/dotnet/building-resilient-cloud-services-with-dotnet-8/)
+
+## With Flurl
+
+[Flurl](https://flurl.dev/) is a URL builder and HTTP client library for .NET.
+
+The named `HttpClient` registration and its decoration with our resilience strategy are the same as the built-in `HttpClient`.
+
+Here we create a `FlurlClient` which uses the decorated, named `HttpClient` for HTTP requests.
+
+
+```cs
+var services = new ServiceCollection();
+
+// Register a named HttpClient and decorate with a resilience pipeline
+services.AddHttpClient(HttpClientName)
+ .ConfigureHttpClient(client => client.BaseAddress = BaseAddress)
+ .AddResilienceHandler("flurl_based_pipeline",
+ builder => builder.AddRetry(GetRetryOptions()));
+
+using var provider = services.BuildServiceProvider();
+
+// Resolve the named HttpClient and create a new FlurlClient
+var httpClientFactory = provider.GetRequiredService();
+var flurlClient = new FlurlClient(httpClientFactory.CreateClient(HttpClientName));
+
+// Use the FlurlClient by making a request
+var response = await flurlClient.Request("/408").GetAsync();
+```
+
+
+> [!NOTE]
+> The following packages are required to the above example:
+>
+> - [Microsoft.Extensions.DependencyInjection](https://www.nuget.org/packages/microsoft.extensions.dependencyinjection): Required for the dependency injection functionality
+> - [Microsoft.Extensions.Http.Resilience](https://www.nuget.org/packages/Microsoft.Extensions.Http.Resilience): Required for the `AddResilienceHandler` extension
+> - [Flurl.Http](https://www.nuget.org/packages/Flurl.Http/): Required for the `FlurlClient`
+
+### Further reading for Flurl
+
+- [Flurl home page](https://flurl.dev/)
+
+## With Refit
+
+[Refit](https://github.com/reactiveui/refit) is an automatic type-safe REST library for .NET.
+
+First let's define the API interface:
+
+
+```cs
+public interface IHttpStatusApi
+{
+ [Get("/408")]
+ Task GetRequestTimeoutEndpointAsync();
+}
+```
+
+
+Then use the `AddRefitClient` method to register the interface as a typed `HttpClient`. Finally we call `AddResilienceHandler` to decorate the underlying `HttpClient` with our resilience strategy.
+
+
+```cs
+var services = new ServiceCollection();
+
+// Register a Refit generated typed HttpClient and decorate with a resilience pipeline
+services.AddRefitClient()
+ .ConfigureHttpClient(client => client.BaseAddress = BaseAddress)
+ .AddResilienceHandler("refit_based_pipeline",
+ builder => builder.AddRetry(GetRetryOptions()));
+
+// Resolve the typed HttpClient
+using var provider = services.BuildServiceProvider();
+var apiClient = provider.GetRequiredService();
+
+// Use the Refit generated typed HttpClient by making a request
+var response = await apiClient.GetRequestTimeoutEndpointAsync();
+```
+
+
+> [!NOTE]
+> The following packages are required to the above example:
+>
+> - [Microsoft.Extensions.DependencyInjection](https://www.nuget.org/packages/microsoft.extensions.dependencyinjection): Required for the dependency injection functionality
+> - [Refit.HttpClientFactory](https://www.nuget.org/packages/Refit.HttpClientFactory): Required for the `AddRefitClient` extension
+
+### Further readings for Refit
+
+- [Using ASP.NET Core 2.1's HttpClientFactory with Refit's REST library](https://www.hanselman.com/blog/using-aspnet-core-21s-httpclientfactory-with-refits-rest-library)
+- [Refit in .NET: Building Robust API Clients in C#](https://www.milanjovanovic.tech/blog/refit-in-dotnet-building-robust-api-clients-in-csharp)
+- [Understand Refit in .NET Core](https://medium.com/@jaimin_99136/understand-the-refit-in-net-core-ba0097c5e620)
+
+## With RestSharp
+
+[RestSharp](https://restsharp.dev/) is a simple REST and HTTP API Client for .NET.
+
+The named `HttpClient` registration and its decoration with our resilience strategy are the same as the built-in `HttpClient`.
+
+Here we create a `RestClient` which uses the decorated, named `HttpClient` for HTTP requests.
+
+
+```cs
+var services = new ServiceCollection();
+
+// Register a named HttpClient and decorate with a resilience pipeline
+services.AddHttpClient(HttpClientName)
+ .ConfigureHttpClient(client => client.BaseAddress = BaseAddress)
+ .AddResilienceHandler("restsharp_based_pipeline",
+ builder => builder.AddRetry(GetRetryOptions()));
+
+using var provider = services.BuildServiceProvider();
+
+// Resolve the named HttpClient and create a RestClient
+var httpClientFactory = provider.GetRequiredService();
+var restClient = new RestClient(httpClientFactory.CreateClient(HttpClientName));
+
+// Use the RestClient by making a request
+var request = new RestRequest("/408", Method.Get);
+var response = await restClient.ExecuteAsync(request);
+```
+
+
+> [!NOTE]
+> The following packages are required to the above example:
+>
+> - [Microsoft.Extensions.DependencyInjection](https://www.nuget.org/packages/microsoft.extensions.dependencyinjection): Required for the dependency injection functionality
+> - [Microsoft.Extensions.Http.Resilience](https://www.nuget.org/packages/Microsoft.Extensions.Http.Resilience): Required for the `AddResilienceHandler` extension
+> - [RestSharp](https://www.nuget.org/packages/RestSharp): Required for the `RestClient`, `RestRequest`, `RestResponse`, etc. types
+
+### Further reading for RestSharp
+
+- [RestSharp home page](https://restsharp.dev/)
diff --git a/docs/community/toc.yml b/docs/community/toc.yml
index 0d91ca86bf3..dd539a2fcd2 100644
--- a/docs/community/toc.yml
+++ b/docs/community/toc.yml
@@ -8,3 +8,5 @@
href: git-workflow.md
- name: Cheat sheets
href: cheat-sheets.md
+- name: HTTP client integration samples
+ href: http-client-integrations.md
diff --git a/src/Snippets/Docs/HttpClientIntegrations.cs b/src/Snippets/Docs/HttpClientIntegrations.cs
new file mode 100644
index 00000000000..7f23eaa7193
--- /dev/null
+++ b/src/Snippets/Docs/HttpClientIntegrations.cs
@@ -0,0 +1,132 @@
+using System.Net;
+using System.Net.Http;
+using Flurl.Http;
+using Microsoft.Extensions.DependencyInjection;
+using Polly.Retry;
+using Refit;
+using RestSharp;
+
+namespace Snippets.Docs;
+
+internal static class HttpClientIntegrations
+{
+ private const string HttpClientName = "httpclient";
+ private static readonly Uri BaseAddress = new("https://httpstat.us/");
+
+ #region http-client-integrations-handle-transient-errors
+ private static ValueTask HandleTransientHttpError(Outcome outcome) =>
+ outcome switch
+ {
+ { Exception: HttpRequestException } => PredicateResult.True(),
+ { Result.StatusCode: HttpStatusCode.RequestTimeout } => PredicateResult.True(),
+ { Result.StatusCode: >= HttpStatusCode.InternalServerError } => PredicateResult.True(),
+ _ => PredicateResult.False()
+ };
+
+ private static RetryStrategyOptions GetRetryOptions() =>
+ new()
+ {
+ ShouldHandle = args => HandleTransientHttpError(args.Outcome),
+ MaxRetryAttempts = 3,
+ BackoffType = DelayBackoffType.Exponential,
+ Delay = TimeSpan.FromSeconds(2)
+ };
+ #endregion
+
+#pragma warning disable CA2234
+ public static async Task HttpClientExample()
+ {
+ #region http-client-integrations-httpclient
+ var services = new ServiceCollection();
+
+ // Register a named HttpClient and decorate with a resilience pipeline
+ services.AddHttpClient(HttpClientName)
+ .ConfigureHttpClient(client => client.BaseAddress = BaseAddress)
+ .AddResilienceHandler("httpclient_based_pipeline",
+ builder => builder.AddRetry(GetRetryOptions()));
+
+ using var provider = services.BuildServiceProvider();
+
+ // Resolve the named HttpClient
+ var httpClientFactory = provider.GetRequiredService();
+ var httpClient = httpClientFactory.CreateClient(HttpClientName);
+
+ // Use the HttpClient by making a request
+ var response = await httpClient.GetAsync("/408");
+ #endregion
+ }
+#pragma warning restore CA2234
+
+ public static async Task RefitExample()
+ {
+ #region http-client-integrations-refit
+ var services = new ServiceCollection();
+
+ // Register a Refit generated typed HttpClient and decorate with a resilience pipeline
+ services.AddRefitClient()
+ .ConfigureHttpClient(client => client.BaseAddress = BaseAddress)
+ .AddResilienceHandler("refit_based_pipeline",
+ builder => builder.AddRetry(GetRetryOptions()));
+
+ // Resolve the typed HttpClient
+ using var provider = services.BuildServiceProvider();
+ var apiClient = provider.GetRequiredService();
+
+ // Use the Refit generated typed HttpClient by making a request
+ var response = await apiClient.GetRequestTimeoutEndpointAsync();
+ #endregion
+ }
+
+ public static async Task FlurlExample()
+ {
+ #region http-client-integrations-flurl
+ var services = new ServiceCollection();
+
+ // Register a named HttpClient and decorate with a resilience pipeline
+ services.AddHttpClient(HttpClientName)
+ .ConfigureHttpClient(client => client.BaseAddress = BaseAddress)
+ .AddResilienceHandler("flurl_based_pipeline",
+ builder => builder.AddRetry(GetRetryOptions()));
+
+ using var provider = services.BuildServiceProvider();
+
+ // Resolve the named HttpClient and create a new FlurlClient
+ var httpClientFactory = provider.GetRequiredService();
+ var flurlClient = new FlurlClient(httpClientFactory.CreateClient(HttpClientName));
+
+ // Use the FlurlClient by making a request
+ var response = await flurlClient.Request("/408").GetAsync();
+ #endregion
+ }
+
+ public static async Task RestSharpExample()
+ {
+ #region http-client-integrations-restsharp
+ var services = new ServiceCollection();
+
+ // Register a named HttpClient and decorate with a resilience pipeline
+ services.AddHttpClient(HttpClientName)
+ .ConfigureHttpClient(client => client.BaseAddress = BaseAddress)
+ .AddResilienceHandler("restsharp_based_pipeline",
+ builder => builder.AddRetry(GetRetryOptions()));
+
+ using var provider = services.BuildServiceProvider();
+
+ // Resolve the named HttpClient and create a RestClient
+ var httpClientFactory = provider.GetRequiredService();
+ var restClient = new RestClient(httpClientFactory.CreateClient(HttpClientName));
+
+ // Use the RestClient by making a request
+ var request = new RestRequest("/408", Method.Get);
+ var response = await restClient.ExecuteAsync(request);
+ #endregion
+ }
+}
+
+#region http-client-integrations-refit-interface
+public interface IHttpStatusApi
+{
+ [Get("/408")]
+ Task GetRequestTimeoutEndpointAsync();
+}
+#endregion
diff --git a/src/Snippets/Snippets.csproj b/src/Snippets/Snippets.csproj
index a5432022f89..78f29eae35e 100644
--- a/src/Snippets/Snippets.csproj
+++ b/src/Snippets/Snippets.csproj
@@ -22,6 +22,9 @@
+
+
+