Delphi - Indy (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;
我有一个网站,需要我保持会话活动。我该怎么做?使用与上面类似的代码。
如果我为所有内容创建一个可视组件,并使用它,一切都很棒,但是当我动态创建该组件时(我真的想以这种方式保留它),它无法使会话保持活动状态。
任何帮助表示赞赏。
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.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
我没有看到你在哪里实例化 CookieManager,但那是你应该跟踪会话的地方。服务器将发送一些代表当前会话的 cookie,并且您发送到服务器的所有进一步请求都应包含该 cookie,以便服务器知道要使用哪个会话。
您必须在会话期间保留 cookie 管理器对象,或者必须将其数据保存在其他位置,然后在每次创建新的 cookie 管理器对象时重新加载它。我更喜欢前者。事实上,您可能会考虑保留整个 HTTP 对象。
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.
正如您在评论中提到的,您正在 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 过程。
问候
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
正如 Rob 所说,您的 TIdCookieManager 是维护基于 Cookie 的会话的关键。 TIdCookieManager 可以在数据模块的创建事件或主窗体 OnCreate() 事件中创建,然后在每次创建 IdHTTP 组件时进行设置。
As Rob said your TIdCookieManager is key for maintaining a Cookie based session. The TIdCookieManager could be created in a datamodule's create event or the mainforms OnCreate() event and then set every time you create a IdHTTP component.