簡體   English   中英

使用 Indy + SSL + 代理發布

[英]POST with Indy + SSL + Proxy

我正在嘗試使用 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。”

現在,有趣的部分來了:

  1. 如果根本不使用代理(即不設置 FHttp.ProxyParams 設置) - 一切正常。
  2. 如果沒有設置任何 POST 參數(即空 FParams),但仍在使用代理- 一切正常。
  3. 最奇怪的一個:如果我正在逐步調試 Indy 代碼(TIdCustomHTTP.DoRequest 方法) - 上面的示例一切正常(代理設置 + 參數)。

POST 參數由於某種原因沒有正確發送?

為什么會發生第 3 步?

Indy 是最新的,剛剛從存儲庫中提取

更新

攔截 TIdHTTP 調用(感謝Remy )后,清晰度會更高一些。 失敗日志工作日志)。

簡短版本:在進行調試時,Indy 會執行 3 個 CONNECT + POST + DISCONNECT 請求(因為我相信服務上有重定向)並且它可以工作。

在沒有調試的情況下運行測試時 - CONNECT + DISCONNECT + POST - 它顯然失敗了(即在前面沒有 CONNECT 的情況下執行 POST)。 有關詳細信息,請參閱附加的日志文件。

您在TIdHTTP中發現了一些需要修復的邏輯錯誤。 我為此開了一張新票:

#315:TIdHTTP 代理處理中的錯誤


這是我在您的“失敗”場景中看到的情況:

TIdHTTP連接代理,發送CONNECT請求成功連接到my.service.com:443 ,然后發送POST請求(使用 HTTP 1.0 而不是Z293C9EA246FF9985DC6F62A1650)

a) 要使用 HTTP 1.1 發送POST請求,您必須將TIdHTTP.ProtocolVersion屬性設置為pv1_1 ,並在TIdHTTP.HTTPOptions屬性中啟用hoKeepOrigProtocol標志。 否則, TIdHTTP.Post()ProtocolVersion強制為pv1_0

HTTP 服務器回復302 Found響應重定向到不同的 URL,包括Keep-Alive header,如果在下一個請求中未發送新連接,則表明服務器將關閉。

TIdHTTP完成對POST響應的處理后,它知道它將向新的 URL 重新發送相同的請求。 在下一次循環迭代中,它看到目標服務器是相同的,並且代理仍然連接,因此連接沒有關閉,並且會發送新的CONNECT請求的代碼被跳過。

就在發送POST請求之前,會檢查Response.KeepAlive屬性以確定是否要關閉套接字連接。 KeepAlive屬性 getter 看到ProtocolVersion屬性是pv1_0並且沒有Proxy-Connection: keep-alive header 出現在響應中(即使有一個Connection: keep-alive標頭),所以它返回 False,然后是套接字連接關閉。

TIdHTTP然后再次重新連接到代理,但在發送POST請求之前不會發送新的CONNECT請求。 代理不知道如何處理POST ,因此它以400 Bad Request響應使請求失敗。


這是我在您的“工作”場景中看到的情況:

一切都與上面相同,直到處理第一個POST請求。 然后會有大約 16 秒的延遲(可能是因為您正在單步執行代碼) - 超過 5 秒的Keep-Alive延遲允許 - 所以 HTTP 服務器關閉與代理的連接,然后關閉與TIdHTTP的連接。

TIdHTTP准備發送第二個POST請求時,它知道它已經與代理斷開連接,所以它重新連接到代理,發送一個新的CONNECT請求,然后發送POST請求。


在我可以正確修復錯誤之前,請嘗試以下操作:

  • TIdHTTP.HTTPOptions屬性中啟用hoKeepOrigProtocol標志以允許TIdHTTP.Post()使用 HTTP 1.1。 這本身可能會解決在將第二個POST請求發送到重定向的 URL 之前不必要地關閉連接的問題。

  • 如果這不能解決問題,請嘗試自己編輯IdHTTP.pas並重新編譯 Indy,以更新TIdCustomHTTP.ConnectToHost()方法以在本地LUseConnectVerb變量設置為之前Response.KeepAlive屬性為 False 時強制Disconnect()ARequest.UseProxyctSSLProxy (和ctProxy也是)的情況下not Connected 這樣,第二個POST請求將與代理斷開連接,並使用新的CONNECT請求重新連接。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM