example url: https://api.binance.com/api/v1/time
Using TIdDNSResolver and cloudflare dns I can get the host IP. direct request in the form of
https://205.251.219.20/api/v1/time
doesn't work cause as I understand the server expects to see "api.binance.com" in the url. (it doesnt work even in browser)
Using synapce and the following patch to replace request's host with resolved IP I make it working
function THTTPSend.InternalDoConnect(needssl: Boolean): Boolean;
begin
Result := False;
FSock.CloseSocket;
FSock.Bind(FIPInterface, cAnyPort);
if FSock.LastError <> 0 then
Exit;
If ResolvedIP.IsEmpty
then FSock.Connect(FTargetHost, FTargetPort)
else FSock.Connect(ResolvedIP, FTargetPort); // !!
Is there any way to do the same using Indy?
By default,
TIdHTTP
uses the Host:Port that is specified/inferred by the URL that is being requested. To change that behavior, you would have to alterTIdHTTP
's source code, such as in theTIdCustomHTTP.SetHostAndPort()
orTIdCustomHTTP.CheckAndConnect()
method (which are both notvirtual
), and then recompile Indy.Alternatively, you could use
TIdHTTP
'sOnSocketAllocated
orOn(Before|After)Bind
event (which are not promoted topublished
inTIdHTTP
, so you would have to access them manually at runtime) to change theTIdHTTP.IOHandler.Host
property to whatever IP address you want to connect to. This will not have any affect on the HTTP headers thatTIdHTTP
sends, such asHost
, which will still be taken from the URL.Alternatively, if you want all of Indy's Host-to-IP DNS queries to go through Cloudflare, you could derive a custom class from
TIdStack
(or whatever platform-specific descendant you are interested in, such asTIdStackWindows
), override its virtualHostByName()
method to perform whatever DNS query you want, and then pass your class type to theSetStackClass()
function in theIdStack
unit at program startup before any Indy classes are instantiated.