Search code examples
c#.net-5dotnet-httpclient

How to implement Http proxy using .Net 5


I have to implement an HTTP "proxy" service, that will be called internally from other services using a an HttpSettings interface.

Settings should look something like:

interface ISettings {
    string Host { get; set; }
    string Port { get; set; }
    string Username { get; set; }
    string Password { get; set; }
    bool UseSsl { get; set; }
    string ProxyUrl { get; set; }
    string ProxyPort { get; set; }
    string Timeout { get; set; }
    HttpHeaders Headers { get; set; }
}

Due to the generic nature of the service, I cannot predefine named or typed HttpClients as described by MS. From what I understand this means that I cannot use IHttpClientFactory.

Then I'm left with manual instantiation of clients. But that's also problematic:

  • if defined as singletons - network level changes might render them obsolete and unusable.
  • if not singletons - then under heavy load the application will exhaust it's connection pool

Okey, maybe I can define limited amount of singleton clients and reuse them based on the input settings and somehow monitor the networks and implement a mechanism to recreate obsolete instances. I've no idea how to do that, but let say that it's done - not all configuration happens at the HttpClient level. The proxy and network credentials, for example happen at the HttpClientHandler level. And from what I understand HttpClientHandler should be a singleton. If it is, how can I configure concurrent HttpClient calls with different proxy and credential settings?


Solution

  • Disclaimer

    I don't know if it's the best approach, but it is a solution. Granted, I'm not sure it solves the network problems, which may occur if using singleton clients. If those problems originate from the HttpClientHandler then they will probably persist. In our case, we'll monitor and take further action if necessary.

    Solution

    It turns out that it's not the HttpClient itself that occupies the connections, but it's the HttpClientHandler. That allows us to create new clients for every request and reuse a concurrent HttpClientHandler instance.

    The only thing that remains than is support for concurrent calls with proxy settings. Since those settings are configured on the HttpClientHandler itself we can solve that by creating our own managed pool of handlers. When a request comes in with proxy settings all existing instances of HttpClientHandler will be checked if they are currently in use. If no instance is available a new one will be created and added to the pool.