Delphi Indy如何使用自定义DNS解析进行https请求

4
示例网址: https://api.binance.com/api/v1/time 使用 TIdDNSResolver 和 Cloudflare DNS,我可以获取主机 IP。直接请求的形式为: https://205.251.219.20/api/v1/time 不起作用,因为我理解服务器期望在 URL 中看到 "api.binance.com"。(即使在浏览器中也无法工作)
使用 Synapce 并使用以下补丁替换请求的主机名为已解析的 IP,使其正常工作。
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);   // !!

有没有使用Indy实现相同功能的方法?
1个回答

5
默认情况下,TIdHTTP 使用由请求的 URL 指定或推断出的主机名和端口。若要更改此行为,您需要修改 TIdHTTP 的源代码,例如在 TIdCustomHTTP.SetHostAndPort()TIdCustomHTTP.CheckAndConnect() 方法中(二者均不是 virtual),然后重新编译 Indy。
或者,您可以使用 TIdHTTPOnSocketAllocatedOn(Before|After)Bind 事件(二者都没有在 TIdHTTP 中发布,因此您需要在运行时手动访问它们)将 TIdHTTP.IOHandler.Host 属性更改为您想要连接的任何 IP 地址。这不会对 TIdHTTP 发送的 HTTP 标头产生任何影响,例如 Host,该标头仍将来自于 URL。
另外,如果您希望所有 Indy 的主机到 IP DNS 查询都通过 Cloudflare 进行,则可以从 TIdStack(或您感兴趣的任何特定平台后代,例如 TIdStackWindows)派生一个自定义类,覆盖其虚拟的 HostByName() 方法以执行您想要的任何 DNS 查询,然后在任何 Indy 类被实例化之前,在程序启动时将您的类类型传递给 IdStack 单元中的 SetStackClass() 函数。

3D解决方案非常完美,非常感谢!我不想重新编译系统代码,所以 SetStackClass(TCustomStack); 正是我需要的。 - Michael Gendelev
请问您能否添加一个简单的解决方案到TNetHTTPClient中吗? - Michael Gendelev
@MichaelGendelev 这应该是一个新问题(这个问题特定于Indy库),但如果您有TNetHTTPClient的源代码,也许可以以类似的方式实现。 - mjn42

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接