[英]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。”
現在,有趣的部分來了:
POST 參數由於某種原因沒有正確發送?
為什么會發生第 3 步?
Indy 是最新的,剛剛從存儲庫中提取
更新
攔截 TIdHTTP 調用(感謝Remy )后,清晰度會更高一些。 ( 失敗日志, 工作日志)。
簡短版本:在進行調試時,Indy 會執行 3 個 CONNECT + POST + DISCONNECT 請求(因為我相信服務上有重定向)並且它可以工作。
在沒有調試的情況下運行測試時 - CONNECT + DISCONNECT + POST - 它顯然失敗了(即在前面沒有 CONNECT 的情況下執行 POST)。 有關詳細信息,請參閱附加的日志文件。
您在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.UseProxy
是ctSSLProxy
(和ctProxy
也是)的情況下not Connected
。 這樣,第二個POST
請求將與代理斷開連接,並使用新的CONNECT
請求重新連接。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.