Delphi - Indy(IDHTTP)保持会话

5

好的,我创建了一个动态的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
我看不到你在哪里实例化CookieManager,但这是你应该跟踪会话的地方。服务器将发送一些代表当前会话的cookie,您发送给服务器的所有后续请求都应包含该cookie,以便服务器知道使用哪个会话。
您必须保留cookie管理器对象以用于会话的持续时间,或者您必须将其数据保存在其他地方,然后每次创建新的cookie管理器对象时重新加载它。我更喜欢前者。事实上,您可能考虑保留整个HTTP对象。

我忘记复制那段代码了... 我试过在onCreate事件中放置Cookie Manager,然后让它保持不为空,但似乎没有起作用。至于保留HTTP对象,我并不是真的想这么做,但我可以试试看。我会看看当我保持http对象时会发生什么。其实我真的不想这样做(没有特别的原因)... - Brad

2
正如您在评论中提到的,您正在OnCreate事件处理程序中创建CookieManager,这样当调用TForm1.webSession时,CookieManager就可用了。但是在TForm1.webSession的finally块中,您释放了CookieManager,因此一旦离开TForm1.webSession方法,CookieManager就会被释放出内存。因此,下次调用TForm1.webSession时,CookieManager为Nil,您将无法保存任何cookie。

还有两个与您的问题无关但与您的源代码相关的注意事项:

1- 您的方法返回AnsiString,但您使用Utf8ToWideString来为Result变量赋值。 Utf8ToWideString返回WideString,因此编译器必须将WideString转换为AnsiString,这不仅降低了性能,而且还使返回字符串中的unicode字符丢失。您应该更改方法签名以返回String(D2009&D2010)或WideString(Delphi的旧版本)。

2- 在finally块中,您不需要检查SStream、AntiFreeze或HTTPCon是否已分配。您可以简单地调用Free方法或使用FreeAndNil过程。

问候


感谢您提供有关 AnsiString 的信息,我将编辑工作代码以修复此问题。在我拥有 CookieManager 的代码中,在 OnCreate 事件中,我没有在那个版本中使用 freeandnil 代码。 - Brad

1
正如Rob所说,您的TIdCookieManager对于维护基于Cookie的会话非常关键。 TIdCookieManager可以在datamodule的create事件或主窗体的OnCreate()事件中创建,然后在每次创建IdHTTP组件时进行设置。

我会再尝试一下OnCreate,我之前在表单上写成了OnCreate。(顺便说一句,谢谢你之前提供的代码,它在处理这个网站和维护会话方面非常有效。) - Brad
没问题,很高兴能帮忙!-你有考虑使用线程来处理通讯部分吗?如果可以在你的代码中实现,可能会使程序运行更平稳。 - K.Sandell
是的,我一直在看一个关于线程的演示,但是线程对我来说超出了我的Delphi当前知识水平。而且这个项目大部分时间都需要反复联系同一个网站,所以我不需要/不想为这一个请求建立多个线程。但是我在另外几个项目中使用了相同的基础代码,如果能够将它们加入线程就更好了。你有没有什么好的线程演示建议? - Brad
这是一个相当大的主题,因此提出一个新问题可能是最好的方式。我绝对可以在这方面提供帮助,但具体的实现可能会因使用和需求而异... - K.Sandell

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接