Search code examples
c#asp.net-coreflurl

How to set up a proxy server for a flurl client selectively?


Is there a recommended way of defining a proxy for flurl clients based on the URL (or base URL)? I could not find anything in the documentation and discussions of the topic I did find (such as Setting a per-request proxy (or rotating proxies) with .NET Flurl/HttpClient) focuses on somewhat more complicated cases and How can I use proxies for web requests in Flurl? seems to set up the setting that would affect all calls (unless I misunderstood it).

In our scenario, an app calls different endpoints (other apps). Some of these endpoints can only be reached via a proxy server, some can be reached directly. Also, in some environments (DEV vs. PREPROD vs PROD), the same endpoints may need or not need a proxy, so the configuration could be similar to:

DEV

PREPROD

PROD

In this scenario, I assume that we need three HTTP clients (X, Y, and Z). What would be the right way to configure proxy settings for these clients?


Solution

  • I would suggest creating a new HttpClient factory that accepts a proxy address as described here, but rather than registering it globally, create a FlurlClientFactory as described here that overrides FlurlClientFactoryBase and uses the proxy address at the cache key, guaranteeing exactly 1 FlurlClient per proxy.

    public class ProxyFlurlClientFactory : FlurlClientFactoryBase
    {
        protected override string GetCacheKey(Url url) => GetProxyForUrl(Url url);
    
        // Guaranteed to be called only once per proxy
        protected override IFlurlClient Create(Url url) {
            var httpFac = new ProxyHttpClientFactory(GetProxyForUrl(Url url));
            return new FlurlClient().Configure(settings => settings.HttpClientFactory = httpFac));
        }
        
        private string GetProxyForUrl(Url url) => ???; // whatever your rules are to pick the right one
    }
    

    This can be registered globally:

    FlurlHttp.Configure(settings => settings.FlurlClientFactory = new ProxyFlurlClientFactory());
    

    Or inject it via the DI pattern if you prefer.