Skip to content

Instantly share code, notes, and snippets.

@Wind010
Created February 21, 2020 02:07
Show Gist options
  • Save Wind010/11b20e780269830d2163d0faedec3039 to your computer and use it in GitHub Desktop.
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
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