delphi - 使用 Indy + SSL + 代理发布

标签 delphi ssl proxy indy idhttp

我正在尝试使用 https 通过代理发出 POST 请求。
代码如下:

  FHttp := TIdHttp.Create(nil);

  FHttp.ProxyParams.ProxyServer := Host;
  FHttp.ProxyParams.ProxyPort := Port;
  FHttp.ProxyParams.ProxyUsername := User;
  FHttp.ProxyParams.ProxyPassword := Password;

  FHandler := TIdSSLIOHandlerSocketOpenSSL.Create(nil);
  FHandler.SSLOptions.Method := sslvTLSv1_2;
  FHandler.PassThrough := true;
  FHttp.IOHandler := FHandler;
  FHttp.HandleRedirects := true;
  FHttp.Request.ContentType := 'application/x-www-form-urlencoded';
  FHttp.Request.Connection := 'keep-alive';
  FHttp.Request.ProxyConnection := 'keep-alive';
...

  FParams.Add('username=user');
  FParams.Add('password=pwd');
  FHttp.Post('https://my.service/login', FParams);
代理服务器是 Squid。
代码生成错误“Socket Error # 10054 Connection reset by peer。”
现在,有趣的部分来了:
  • 如果根本不使用代理(即不设置 FHttp.ProxyParams 设置) - 一切正常。
  • 如果未设置任何 POST 参数(即空 FParams),但仍为 使用代理 - 一切都好。
  • 最奇怪的一个:如果我正在逐步调试 Indy 代码(TIdCustomHTTP.DoRequest 方法) - 上面的示例一切正常(代理设置 + 参数)。

  • POST 参数由于某种原因没有正确发送?
    为什么会发生第 3 步?
    Indy 是最新的,刚刚从存储库中提取
    更新
    拦截 TIdHTTP 调用后(感谢 Remy )有一点更清晰。 (failing logworking log)。
    简短版本:在进行调试时,Indy 会执行 3 个 CONNECT + POST + DISCONNECT 请求(因为我相信服务上有重定向)并且它可以工作。
    在没有调试的情况下运行测试时 - CONNECT + DISCONNECT + POST - 它显然失败了(即在前面没有 CONNECT 的情况下执行 POST)。
    有关详细信息,请参阅附加的日志文件。

    最佳答案

    您在 TIdHTTP 中发现了一些逻辑错误。需要修复。我为此开了一张新票:
    #315: Bugs in TIdHTTP proxy handling

    这是我在您的“失败”场景中看到的情况:TIdHTTP连接到代理,发送 CONNECT成功连接到 my.service.com:443 的请求,然后发送 POST请求(使用 HTTP 1.0 而不是 HTTP 1.1 a)。
    a) 发送 POST使用 HTTP 1.1 请求,您必须设置 TIdHTTP.ProtocolVersion属性(property)给 pv1_1 , 并启用 hoKeepOrigProtocol TIdHTTP.HTTPOptions 中的标志属性(property)。否则,TIdHTTP.Post()强制ProtocolVersionpv1_0 .
    HTTP 服务器回复 302 Found重定向到不同 URL 的响应,包括 Keep-Alive header 表示如果在接下来的 5 秒内没有发送新请求,服务器将关闭连接。
    TIdHTTP处理完 POST响应,它知道它将重新发送相同的请求到一个新的 URL。在下一次循环迭代中,它看到目标服务器是相同的,并且代理仍然连接,因此连接没有关闭,并且会发送新的 CONNECT 的代码请求被跳过。
    就在 POST 之前请求已发送,Response.KeepAlive检查属性以确定是否关闭套接字连接。 KeepAlive属性 getter 看到 ProtocolVersion属性是 pv1_0并且没有Proxy-Connection: keep-alive响应中存在 header (即使有 Connection: keep-alive header ),因此它返回 False,然后关闭套接字连接。TIdHTTP然后再次重新连接到代理,但不发送新的 CONNECT发送 POST 之前的请求要求。代理不知道如何处理 POST ,因此请求失败并返回 400 Bad Request回复。

    这是我在您的“工作”场景中看到的情况:
    一切都和上面一样,直到第一个 POST请求被处理。然后会有大约 16 秒的延迟(可能是因为您正在单步执行代码) - 超过 5 秒 Keep-Alive延迟允许 - 所以 HTTP 服务器关闭它与代理的连接,然后关闭它到 TIdHTTP 的连接.
    到时候TIdHTTP准备发送第二个POST请求,它知道它已经与代理断开连接,所以它重新连接到代理,发送一个新的CONNECT请求,然后发送 POST要求。

    在我可以正确修复错误之前,请尝试以下操作:

  • 启用 hoKeepOrigProtocol TIdHTTP.HTTPOptions 中的标志允许的属性TIdHTTP.Post()使用 HTTP 1.1。这本身可能会解决在发送第二个 POST 之前不必要地关闭连接的问题。请求重定向的 URL。
  • 如果这不能解决问题,请尝试编辑 IdHTTP.pas自己重新编译 Indy,以更新 TIdCustomHTTP.ConnectToHost()强制 Disconnect() 的方法如果 Response.KeepAlive属性在本地 LUseConnectVerb 之前为 False变量设置为 not ConnectedARequest.UseProxy 的情况下是 ctSSLProxy (和 ctProxy 也是)。这样,第二个 POST请求将断开与代理的连接并使用新的 CONNECT 重新连接要求。
  • 关于delphi - 使用 Indy + SSL + 代理发布,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62836672/

    相关文章:

    delphi - 相同的代码,缺少 qtintf70.dll

    java - 我可以在端口 443 上安全地运行 Tomcat 而在 8080 上不安全地运行吗

    python - 在 Twisted 中将 HTTP 代理转换为 HTTPS 代理

    redirect - Nginx 配置代理传递给外部 ip 和端口 (https -> http)

    delphi - 使用 SHGetSpecialFolderPath 检索非管理员用户也可以访问的应用程序文件夹,选择哪个 CSIDL?

    windows - 检测键盘或鼠标事件是否由软件触发

    delphi - 在 Rad Studio 开发环境中将 Delphi 10.1 连接到 Interbase XE7 Desktop

    ASP.NET - 帮助测试和调试 PKI 身份验证

    python - SSL 包装套接字 : AttributeError: 'module' object has no attribute 'wrap_socket'

    node.js - 使用 nginx 的 Websocket 代理不适用于 tomcat。