2010-02-14 81 views
5

好吧,我有Idhttp動態創建類似下面的德爾福 - 印地(IDHTTP)保持會話


procedure TForm1.Button1Click(Sender: TObject); 
Var 
    Resp : String; 
begin 
    Resp := webSession('https://www.website.com'); // HTTPS site requires session to keep alive 
    if Length(Resp)>0 then 
     MessageDlg('Got the body ok',mtInformation,[mbOk],0); 
end; 

function TForm1.webSession(sURL : ansistring) : ansistring; 
var 
    SStream : Tstringstream; 
    HTTPCon : TIdHTTP; 
    AntiFreeze : TIdAntiFreeze; 
    CompressorZLib: TIdCompressorZLib; 
    ConnectionIntercept: TIdConnectionIntercept; 
    SSLIOHandlerSocketOpenSSL: TIdSSLIOHandlerSocketOpenSSL; 
    CookieManager: TIdCookieManager; 
begin 
    CompressorZLib := TIdCompressorZLib.Create; 
    ConnectionIntercept :=TIdConnectionIntercept.Create; 
    SSLIOHandlerSocketOpenSSL := TIdSSLIOHandlerSocketOpenSSL.Create; 
    Result := ''; 
    if Length(SettingsForm.edtProxyServer.text) >= 7 then // 0.0.0.0 
    Try 
     SStream := NIL; 
     AntiFreeze := NIL; 
     HTTPCon := NIL; 
     Try 
      SStream := tstringstream.Create(''); 
      { Create & Set IdHTTP properties } 
      HTTPCon := TIdHTTP.create; 
      HTTPCon.AllowCookies:=true; 
      HTTPCon.CookieManager :=CookieManager; 
      HTTPCon.Compressor := CompressorZLib; 
      HTTPCon.Intercept := ConnectionIntercept; 
      HTTPCon.IOHandler := SSLIOHandlerSocketOpenSSL; 
      HTTPCon.HandleRedirects := true; 
      { Check Proxy } 
      if checkproxy('http://www.google.com') then 
      Begin 
       HTTPCon.ProxyParams.ProxyServer := SettingsForm.edtProxyServer.text; 
       HTTPCon.ProxyParams.ProxyPort := StrToInt(SettingsForm.edtProxyPort.Text); 
       HTTPCon.ProxyParams.BasicAuthentication := True; 
       HTTPCon.ProxyParams.ProxyUsername := SettingsForm.edtProxyServer.Text; 
       HTTPCon.ProxyParams.ProxyPassword := SettingsForm.edtProxyUserName.Text; 
      End; 
      { Create another AntiFreeze - only 1/app } 
      AntiFreeze := TIdAntiFreeze.Create(nil); 
      AntiFreeze.Active := true; 
      HTTPCon.Get(sURL,SStream); 
      Result := UTF8ToWideString(SStream.DataString); 
     Finally 
      If Assigned(HTTPCon) then FreeAndNil(HTTPCon); 
      If Assigned(AntiFreeze) then FreeAndNil(AntiFreeze); 
      If Assigned(SStream) then FreeAndNil(SStream); 
      If Assigned(CookieManager) then FreeAndNil (CookieManager); 
      If Assigned(CompressorZLib) then FreeAndNil (CompressorZLib); 
      If Assigned(ConnectionIntercept) then FreeAndNil (ConnectionIntercept); 
      If Assigned(SSLIOHandlerSocketOpenSSL) then FreeAndNil (SSLIOHandlerSocketOpenSSL); 

     End; 
    Except 
     { Handle exceptions } 
     On E:Exception do 
      MessageDlg('Exception: '+E.Message,mtError, [mbOK], 0); 
    End; 
end; 

function TForm1.checkproxy(sURL : ansistring) : boolean; 
var 
    HTTPCon : TIdHTTP; 
    AntiFreeze : TIdAntiFreeze; 
begin 
    Result := False; 
    Try 
     { Inti vars } 
     AntiFreeze := NIL; 
     HTTPCon := NIL; 
     Try 
      { AntiFreeze } 
      AntiFreeze := TIdAntiFreeze.Create(NIL); 
      AntiFreeze.Active := true; 
      { Create & Set IdHTTP properties } 
      HTTPCon := TIdHTTP.Create(NIL); 
      HTTPCon.ProxyParams.ProxyServer := SettingsForm.edtProxyServer.text; 
      HTTPCon.ProxyParams.ProxyPort := StrToInt(SettingsForm.edtProxyPort.Text); 
      HTTPCon.ProxyParams.BasicAuthentication := True; 
      HTTPCon.ProxyParams.ProxyUsername := SettingsForm.edtProxyServer.Text; 
      HTTPCon.ProxyParams.ProxyPassword := SettingsForm.edtProxyUserName.Text; 
      HTTPCon.HandleRedirects := true; 
      HTTPCon.ConnectTimeout := 1000; 
      HTTPCon.Request.Connection := 'close'; 
      HTTPCon.Head(sURL); 
     Finally 
      { Cleanup } 
      if Assigned(HTTPCon) then 
      Begin 
       { Return Success/Failure } 
       Result := HTTPCon.ResponseCode = 200; 
       If HTTPCon.Connected then HTTPCon.Disconnect; 
       FreeAndNil(HTTPCon); 
      End; 
      if Assigned(AntiFreeze) then FreeAndNil(AntiFreeze); 
     End; 
    Except 
     On E:EIdException do ; 
     { Handle exceptions } 
     On E:Exception do 
      MessageDlg('Exception: '+E.Message,mtError, [mbOK], 0); 
    End; 
end; 

我有一個網站,需要我保持會話活着。我將如何做到這一點?與上面類似的代碼。

如果我爲所有東西創建一個可視化組件,並且使用它,一切都很好,但是當我動態創建組件時(我真的想要這樣離開它),它不能保持會話的活躍。

任何幫助表示讚賞。

回答

5

我沒有看到你在哪裏實例化CookieManager,但這是你應該跟蹤會話的地方。服務器將發送一些代表當前會話的cookie,並且您發送給服務器的所有其他請求都應包含該cookie,以便服務器知道要使用哪個會話。

您必須在會話期間保留Cookie管理器對象,否則您必須將其數據保存到別處,然後每次創建新的Cookie管理器時重新加載它目的。我更喜歡前者。實際上,您可能會考慮保留整個HTTP對象。

+0

我忘了爲代碼進行復制。我曾試圖把cookie管理器在onCreate事件,然後離開它周圍(不nil'ing它),但它似乎沒有工作。至於保持HTTP對象,這是我真的不想做的事情,但我可以做到這一點,我猜。當我保持http對象時,我會看到它的作用。我真的不想這樣做(沒有任何推理)...... – Brad 2010-02-14 10:28:41

1

Rob說你的TIdCookieManager是維護基於Cookie的會話的關鍵。 TIdCookieManager可以在數據模塊的創建事件或mainforms OnCreate()事件中創建,然後在每次創建IdHTTP組件時進行設置。

+0

我會再次嘗試一下OnCreate,我將它作爲窗體上的OnCreate。 (順便說一句,感謝代碼之前,它奇妙地起作用,直到我不得不處理這個網站並維持一個會話。) – Brad 2010-02-14 10:30:51

+0

沒問題,很高興有人幫忙! - 你是否使用線程來查看通信部分?如果它可以在你的代碼中實現,那麼可以讓它更平滑一些? – 2010-02-14 13:05:47

+0

是的,我一直在尋找一個線程演示,但線程剛剛超過了我目前在Delphi中的知識水平。而且這個項目所做的很多事情都是一次又一次地聯繫同一個網站,所以我不需要/不需要多次請求這個。但是我在其他幾個項目中使用了相同的基本代碼,並且很高興將它們連接起來。你對一個好的線程演示有什麼建議嗎? – Brad 2010-02-14 19:58:40

2

正如你在你的評論中提到的,你在OnCreate事件處理程序中創建CookieManager,以便當TForm1.webSession被調用時,CookieManager可用,但在TForm1.webSession的finally塊中,你可以釋放CookieManager,所以一次你離開TForm1.webSession方法,CookieManager內存不足。所以,下次調用TForm1.webSession時,CookieManager將爲Nil,並且不會爲您保存Cookie。

但是也有一些不相關的問題,其他兩個音符,但關係到你的源代碼:

1-你的方法返回AnsiString類型,但使用的是Utf8ToWideString分配值結果變量。 Utf8ToWideString返回WideString,因此編譯器必須將WideString轉換爲AnsiString,這不僅會降低性能,還會丟失返回字符串中的unicode字符。您應該更改方法簽名以返回字符串(D2009 & D2010)或WideString(Delphi的舊版本)。

2-您不需要檢查在finally塊中是否分配了SStream,AntiFreeze或HTTPCon。您可以簡單地調用Free方法,或使用FreeAndNil過程。

問候

+0

感謝您對AnsiString的信息,我將編輯工作代碼來解決這個問題。 在我有OnCretae事件中的CookieManager的代碼中,我沒有該版本中的freeandnil代碼。 – Brad 2010-02-14 20:08:00