Delphi - Indy (IDHTTP) Keep Session - PullRequest
       7

Delphi - Indy (IDHTTP) Keep Session

5 голосов
/ 14 февраля 2010

Хорошо, у меня 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;

У меня есть веб-сайт, который требует, чтобы я оставил сеанс в живых.Как бы я это сделал?С кодом, аналогичным приведенному выше.

Если я создаю визуальный компонент для всего и использую его, все замечательно, но когда я динамически создаю компонент (который я ДЕЙСТВИТЕЛЬНО хочу оставить таким образом), он не сможет сохранить сеанс живым.

Любая помощь приветствуется.

Ответы [ 3 ]

5 голосов
/ 14 февраля 2010

Я не вижу, где вы создаете экземпляр CookieManager, но именно здесь вы должны следить за сессией. Сервер отправит некоторый файл cookie, представляющий текущий сеанс, и все последующие запросы, которые вы отправляете на сервер, должны включать этот файл cookie, чтобы сервер знал, какой сеанс использовать.

Вам придется либо держать объект cookie-manager рядом в течение всего сеанса, либо вам придется сохранять его данные в другом месте, а затем перезагружать его каждый раз при создании нового объекта cookie-manager. , Я бы предпочел первое. На самом деле, вы можете рассмотреть возможность сохранения всего HTTP-объекта.

2 голосов
/ 14 февраля 2010

Как вы упомянули в своих комментариях, вы создаете CookieManager в обработчике событий OnCreate, так что когда вызывается TForm1.webSession, CookieManager доступен, но в блоке finally TForm1.webSession вы освобождаете CookieManager, поэтому, как только вы оставить метод TForm1.webSession, CookieManager не хватает памяти. Итак, в следующий раз при вызове TForm1.webSession CookieManager будет иметь значение Nil, и для вас не будет сохранен файл cookie.

Есть еще два примечания, которые не связаны с вашим вопросом, но связаны с вашим исходным кодом:

1 - Ваш метод возвращает AnsiString, но вы используете Utf8ToWideString для присвоения значения переменной Result. Utf8ToWideString возвращает WideString, поэтому компилятор должен преобразовать WideString в AnsiString, и это не только снижает производительность, но также теряет символы Юникода в возвращаемой строке. Вы должны изменить сигнатуру вашего метода, чтобы она возвращала либо String (D2009 & D2010), либо WideString (более старые версии Delphi).

2 - Вам не нужно проверять, назначены ли SStream, AntiFreeze или HTTPCon в блоке finally. Вы можете просто вызвать метод Free или использовать процедуру FreeAndNil.

Привет

1 голос
/ 14 февраля 2010

Как сказал Роб, ваш TIdCookieManager является ключом для поддержки сеанса на основе файлов cookie. TIdCookieManager может быть создан в событии create модуля данных или событии mainforms OnCreate (), а затем установлен каждый раз при создании компонента IdHTTP.

...