How to bypass proxy with IHttpClientFactory

By Mirek on (tags: HttpClient, HttpClientFactory, proxy, categories: architecture, code, web)

In this post I’ll show you how easy it is to configure IHttpClientFactory. Keep reading.

The usage of IHttpClientFactory is widely described here, but in this post we will focus on this part, where the configuration of HttpMessageHandler is described. HttpMessageHandler is actually the object that internally handles the connection state, not the HttpClient itself. The message handlers are also the objects that are pooled and reused internally by IHttpClientFactory as described here.

The case I’m trying to solve is quite straight forward.

  1. We have a .NET 6 desktop application which is calling various external services.
  2. There is a proxy server connection configured on the hosting machine.
  3. As .NET 6 app handles and adopts the proxy settings by default, we need to force disable proxy for some connections.

Now with use of IHttpClientFactory it’s quite easy. Let’s create a proof of concept as a console application in .NET 6.

using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
 
var host = Host
     .CreateDefaultBuilder(args)
     .ConfigureServices(services =>
     {
         services.AddHttpClient("NoProxy")
                 .ConfigurePrimaryHttpMessageHandler(() =>
                 {
                     return new HttpClientHandler
                     {
                         UseProxy = false,
                         Proxy = null
                     };
                 });
         services.AddTransient<IPService>();
     })
     .Build(); host.Start(); var service = host.Services.GetRequiredService<IPService>();

var ip = await service.GetMyIP();
Console.WriteLine($"My IP behind proxy is = {ip}");
ip = await service.GetMyIP_NoProxy();
Console.WriteLine($"My no proxy IP = {ip}"); Console.ReadKey();

What we are doing her is following:

  • configure and build generaic application host
  • register named HttpClient (name=“NoProxy”) and configure its primary message handler to NOT use proxy.
  • register service IPService
  • start host and resove the service

Now the idea is following:

  • application calls external web api which returns caller IP address as plain text
  • one call is performed with regular unmodified http client - the returned IP should equal the proxy server’s IP
  • another call is done with “NoProxy” http client – the returned IP should give the real client IP address as connection by-passes the proxy server

And the IPService class

public class IPService
{
     const string IpAPI = "https://api.ipify.org";
     private readonly IHttpClientFactory httpclientFactory;

     public IPService(IHttpClientFactory httpclientFactory)
     {
         this.httpclientFactory = httpclientFactory;
     }

     public async Task<string> GetMyIP()
     {
         var http = httpclientFactory.CreateClient();
         return await http.GetStringAsync(IpAPI);
     }

     public async Task<string> GetMyIP_NoProxy()
     {
         var http = httpclientFactory.CreateClient("NoProxy");
         return await http.GetStringAsync(IpAPI);
     } }

That’s it!