Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Delphi - Indy (IDHTTP) Keep Session

Ok, I have Idhttp created dynamically like the following


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;

I've got a website that requires me to keep a session alive. How would I do this? With similar code to above.

If I create a visual component for everything, and use it everything is great, but when I dynamically create the component (which I REALLY want to leave it this way) it fails to keep the session alive.

Any help is appreciated.

like image 325
Brad Avatar asked Feb 14 '10 00:02

Brad


2 Answers

I don't see where you instantiate CookieManager, but that's where you should keep track of the session. The server will send some cookie that represents the current session, and all further requests that you send to the server should include that cookie so the server knows which session to use.

You'll have to either keep the cookie-manager object around for the duration of the session, or you'll have to save its data somewhere else and then re-load it each time you create a new cookie-manager object. I'd prefer the former. In fact, you might consider keeping the entire HTTP object around.

like image 127
Rob Kennedy Avatar answered Sep 30 '22 14:09

Rob Kennedy


As you mentioned in your comments, you are creating CookieManager in OnCreate event-handler, so that when TForm1.webSession is called, CookieManager is available, but in the finally block of TForm1.webSession you are freeing CookieManager, so once you leave TForm1.webSession method, CookieManager is out of memory. So, next time TForm1.webSession is called, CookieManager is Nil, and no cookie is saved for you.

There are two other notes that are not related to your question, but are related to your source code:

1- Your method is returning AnsiString, but you are using Utf8ToWideString for assigning value to Result variable. Utf8ToWideString returns WideString, so compiler has to convert WideString to AnsiString, and not only this reduces the performance, but also it loses the unicode characters in the returning string. You should change your method signature to return either String (D2009 & D2010) or WideString (Older versions of Delphi).

2- You don't need to check if SStream, AntiFreeze, or HTTPCon are assigned in the finally block. You can simply call the Free method, or use FreeAndNil procedure.

Regards

like image 33
vcldeveloper Avatar answered Sep 30 '22 16:09

vcldeveloper