2

I need to call the same API many times, but with different IP's based on certain parameters.

I've implemented the code in this SO question: how to change originating IP in HttpWebRequest

This worked well when I needed to specify a single IP for the API I am calling, but now I need to use from several ips based on my requirements, and this method no longer seems to work. The api url seems to be cached and subsequent calls will use that IP, instead of the specific one I wish to set on every call.

I need a method that will let me very specifically choose the source IP for each request.

adding:

If I split my application into two separate apps, each one using its own source ip, would this be a brute force approach to force it to work? in other words, is the caching performed only per process? (I assume this is so).

Community
  • 1
  • 1
Brady Moritz
  • 8,624
  • 8
  • 66
  • 100

2 Answers2

1

Using HttpWebRequest.ConnectionGroupName you should be able to get around the ServicePoint connection reuse.

var hr = (HttpWebRequest)WebRequest.Create("http://google.com?");
hr.ConnectionGroupName = hr.RequestUri.ToString(); //Different connection pool per url. Might be better to make this random.
hr.GetResponse();

Alternatively you can just force close the group using ServicePoint.CloseConnectionGroup. The default group is null.

var hr = (HttpWebRequest)WebRequest.Create("http://google.com");
hr.ServicePoint.CloseConnectionGroup(null);
hr.GetResponse();
Will
  • 10,013
  • 9
  • 45
  • 77
  • Will, can I keep two pools, using my own custom names for them? The problem with this code is I'm trying to call the same api at the same URL, with different ips. – Brady Moritz Aug 12 '13 at 20:36
  • Yes, the connection pools are grouped by the group name. Specifying a different group name will create another connection pool(thus a different local ip). Also you can call CloseConnectionGroup which will release the connection pool causing the ServicePoint to create another one(thus a different local ip). – Will Aug 12 '13 at 20:39
  • awesome, I'll give it a try – Brady Moritz Aug 12 '13 at 21:24
  • so Im going to try: Create Request, Set Connection Name, assign BindIPEndPointDelegate delegate... in that order – Brady Moritz Aug 12 '13 at 22:12
  • @boomhauer, what didn't work? Also did you try CloseConnectionGroup? – Will Aug 18 '13 at 23:23
  • I may have other connections using the group, so I don't want to close the whole thing. I'm just trying keepalive=false now to kill off any lingering connections, will report back – Brady Moritz Aug 18 '13 at 23:40
  • @boomhauer, Also why not randomize the group so its unique for every request? – Will Aug 19 '13 at 00:53
  • will, using a unique group per ip should accomplish the same thing, but seems to (at least occasionally) fail. So far, setting keepalive=false has been working, but I hope it doesn't become a bottleneck. – Brady Moritz Aug 19 '13 at 15:04
0

Here is a quick solution you can try without reflecting upon the underlying libraries:

Put some random junk on the end of your target URL e.g.

http://api.address.com/restful/get?param1=a&param2=b&junk=13929348398

You can generate a guid, random number, nanotime, etc. This approach works great for preventing caching of responses -- it should work well in this case also. Do you think this would work for you? Assuming the API ignores that last parameter...

Better yet instead of a random number, you could append a hash of your source IP to actually take advantage of the caching behavior your observing.

mikey
  • 5,090
  • 3
  • 24
  • 27
  • the api calls are passing varying parameters in the querystring already, so I think the connections are being cached internally based on the url (or url and path) only. – Brady Moritz Aug 12 '13 at 18:51
  • to quote a comment on the linked question: The oddity is that it returns the same ServicePoint for any Uri that addresses the same remote IPAddress. – Brady Moritz Aug 12 '13 at 18:53
  • Understood.. back to the drawing board ;) – mikey Aug 12 '13 at 18:57
  • 1
    You've piqued my interest -- I was able to find this SO question (the answer to which is quite informative). http://stackoverflow.com/questions/6114793/binding-an-ip-address-just-works-for-the-first-time I think it matches the issue you're having and lays out some workarounds. EDIT This is actually the question with the comment you quoted (but not the one linked in the question currently). Sorry for pointing it out obviously you've seen this one already also. – mikey Aug 12 '13 at 19:06
  • Perhaps setting KeepAlive = false is an acceptable solution in your case? – mikey Aug 12 '13 at 19:12
  • I just accepted the answer above- the ConnectionGroupName did the trick. Since basically the problem I've having is that the delegate is not called every time- sometimes the connection is reused (that is the key- when they are reused, they keep the old settings, which might be a different source ip). When you set the connectiongroupname, it doesn't matter if they are reused- all the connections in each group use the same source IP. Running for over a day now with no problems! – Brady Moritz Aug 18 '13 at 16:39