Reputation: 481
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?
Upvotes: 4
Views: 874
Reputation: 598448
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 alter TIdHTTP
's source code, such as in the TIdCustomHTTP.SetHostAndPort()
or TIdCustomHTTP.CheckAndConnect()
method (which are both not virtual
), and then recompile Indy.
Alternatively, you could use TIdHTTP
's OnSocketAllocated
or On(Before|After)Bind
event (which are not promoted to published
in TIdHTTP
, so you would have to access them manually at runtime) to change the TIdHTTP.IOHandler.Host
property to whatever IP address you want to connect to. This will not have any affect on the HTTP headers that TIdHTTP
sends, such as Host
, 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 as TIdStackWindows
), override its virtual HostByName()
method to perform whatever DNS query you want, and then pass your class type to the SetStackClass()
function in the IdStack
unit at program startup before any Indy classes are instantiated.
Upvotes: 6