4

I have multiple IPs on the server and would like to chose which one of those I want to use when using HttpClient class to get/post data from an API. (or to even send requests at the same time but utilise the 2 IPs and not just one)

I have seen some examples using HttpWebRequest (here) that utilises delegate but I would like to carry on using HttpClient implementation.

Community
  • 1
  • 1
metase
  • 1,169
  • 2
  • 16
  • 29

1 Answers1

6

[ This will be a hacky code, because there is no method/property to access the ServicePoint ]

You can use reflection to access the underlying ServicePoint as below (Since there is no public/private field/property to access this value, I will hook the startRequest delegate)

HttpClientHandler SetServicePointOptions(HttpClientHandler handler)
{
    var field = handler.GetType().GetField("_startRequest", BindingFlags.NonPublic| BindingFlags.Instance); // Fieldname has a _ due to being private
    var startRequest = (Action<object>)field.GetValue(handler);

    Action<object> newStartRequest = obj =>
    {
        var webReqField = obj.GetType().GetField("webRequest", BindingFlags.NonPublic | BindingFlags.Instance);
        var webRequest = webReqField.GetValue(obj) as HttpWebRequest;
        webRequest.ServicePoint.BindIPEndPointDelegate = new BindIPEndPoint(BindIPEndPointCallback);

        startRequest(obj); //call original action
    };

    field.SetValue(handler, newStartRequest); //replace original 'startRequest' with the one above

    return handler;
}

BindIPEndPointCallback is the one you linked in your question. Modify it as you wish. Now you can use this method like

HttpClientHandler handler = SetServicePointOptions(new HttpClientHandler());
HttpClient client = new HttpClient(handler);
var str = await client.GetStringAsync("https://google.com");
Jaddie
  • 396
  • 3
  • 5
L.B
  • 114,136
  • 19
  • 178
  • 224
  • 3
    Just to put an update to this, for anyone using this code, don't get caught out like I did. Firstly with the fact the .net core team have implemented the HttpClientHandler etc without bothering to put anything related to service points in there, so you'll write all your code to find it silently does nothing, not to mention this code in this example while valid will break. Also speaking of this code the main warning --- the first field name is incorrect it should be _startRequest otherwise you'll get null ref errors & use the full framework not core. – Jaddie Apr 30 '19 at 12:53
  • Thank you so much for your comment. I had the exact same problem, that setting a servicePoint.bindIpEndPointDelegate did work on .net fx but not on .net core! Finally I had to switch my code to .net fx – Pilgerstorfer Franz Aug 04 '21 at 06:56