Created
February 21, 2020 02:07
-
-
Save Wind010/11b20e780269830d2163d0faedec3039 to your computer and use it in GitHub Desktop.
Example of an extension that uses Polly and WebProxy to configure HttpClients created by an IHttpClientFactory
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Configuration; | |
using System.Net; | |
using System.Net.Http; | |
using System.Security.Cryptography.X509Certificates; | |
using Microsoft.Extensions.Configuration; | |
using Microsoft.Extensions.DependencyInjection; | |
namespace Something | |
{ | |
using Polly; | |
public static class ResilientHttpClientWithProxyExtension | |
{ | |
public class ProxySettings : Microsoft.Extensions.Configuration.ConfigurationSection | |
{ | |
[ConfigurationProperty("enableProxy")] | |
public bool EnableProxy { get; set; } | |
[ConfigurationProperty("proxyUri")] | |
public string ProxyUri { get; set; } | |
[ConfigurationProperty("bypassOnLocal")] | |
public bool BypassOnLocal { get; set; } | |
[ConfigurationProperty("bypassList")] | |
public string[] BypassList { get; set; } | |
} | |
public static IServiceCollection AddWebProxy( | |
this IServiceCollection services, IConfigurationRoot configuration, ProxySettings proxySettings = null) | |
{ | |
if (proxySettings == null) | |
{ | |
proxySettings = configuration.GetSection($"{nameof(ProxySettings)}") | |
.Get<ProxySettings>(); | |
} | |
WebProxy webProxy = null; | |
if (proxySettings != null && proxySettings.EnableProxy) | |
{ | |
webProxy = new WebProxy(proxySettings.ProxyUri, | |
proxySettings.BypassOnLocal, | |
proxySettings.BypassList); | |
} | |
if (webProxy != null) | |
{ | |
services.AddSingleton<IWebProxy>(webProxy); | |
} | |
return services; | |
} | |
public static IServiceCollection AddHttpClientWithPollyAndProxy( | |
this IServiceCollection services, IConfigurationRoot configuration, SomeSettings someSettings) | |
{ | |
var sp = services.BuildServiceProvider(); | |
var wrappedPolicies = sp.GetService<IAsyncPolicy<HttpResponseMessage>>(); // Assumes resiliency policies already in container. | |
var webProxy = sp.GetService<IWebProxy>(); // Assumes that a WebProxy was created previously. | |
// Use named client. IHttpClientFactory will be injected to constructors for use. | |
services.AddHttpClient("SomeHttpClient", client => | |
{ | |
client.BaseAddress = new Uri(someSettings.UploadUrl); | |
// Can add other values here like default headers. | |
}) | |
.ConfigurePrimaryHttpMessageHandler(() => GetHttpClientHandler(cert, webProxy)) | |
.AddPolicyHandler(builder => | |
{ | |
// Resolve and apply previously defined resilience policies. | |
// Alternatively could use AddPolicyHandlerFromRegistry, but don't like using | |
// using named policies instead of type. Would make sense if we wanted to | |
// make use of different policies for different clients, but overkill at this point. | |
return wrappedPolicies; | |
}); | |
return services.AddSingleton(someSettings) | |
} | |
private static HttpClientHandler GetHttpClientHandler(X509Certificate2 cert, IWebProxy webProxy) | |
{ | |
var httpClientHandler = new HttpClientHandler | |
{ | |
ClientCertificateOptions = ClientCertificateOption.Manual, | |
}; | |
httpClientHandler.ClientCertificates.Add(cert); | |
if (webProxy != null) | |
{ | |
httpClientHandler.UseProxy = true; | |
httpClientHandler.Proxy = webProxy; | |
} | |
return httpClientHandler; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment