Hi every body,
After working with IdTCPServer, I'm now using IdHTTPServer and for client management I need to use sessions. My web researchs send me to a
Remy's tutorial here
https://forums.embarcadero.com/thread.js...eID=845373 but I always get the following answer
type : exception error
description : the server encounter an internal error that prevented it from fulfilling this request
I believe the forums.embarcadero site is no longer available.
I hope somebody can help me to find this tuto.
Regards
(05-26-2020, 10:43 AM)Alan.F Wrote: [ -> ]I believe the forums.embarcadero site is no longer available.
Correct, it is no longer available, and has not been for some time.
(05-26-2020, 10:43 AM)Alan.F Wrote: [ -> ]I hope somebody can help me to find this tuto.
There is no tutorial, really. Is there something in particular you are having trouble with? To use sessions, simply set the server's
SessionState property to true, tweak its
SessionIDCookieName property if desired, and optionally use its
OnCreateSession and
OnInvalidSession events if needed (if you don't create you own session objects in the
OnCreateSession event, default objects are created automatically). Then you can use the
ARequestInfo.Session.Content and
AResponseInfo.Session.Content properties in the
OnCommand... events to read/write per-session values as needed.
Hi Remy, thank you for your reply. Perhaps it was not a tuto but the link was mentionned to be a "complete example for authentication and users management".
Based on my experience with TidTCPServer I would like to do the following comparisons :
- with TCPServer we can use the "AContext: TIdContext" to manage authentication and specific client management.
- we can use the onconnect and ondisconnect events at the beginning and at the end.
- we can create a "TMyClient = class(TidServerContext)" to keep memory of the session between each automatic run of the TCPServer OnExecute
- we can use TCPserver.Contexts.Locklist to perform safe operations across active connections (count, send message, .....).
- with HTTPServer this has to be done with ARequestInfo: TIdHTTPRequestInfo; AResponseInfo: TIdHTTPResponseInfo
- we can use OnCreateSession and OnSessionEnd
- we can create a "TMySession = class(TIdHTTPSession) to keep memory with the Content
- there is also HTTPserver.Contexts.Locklist but I don't see any access to the sessions list and there is also the HTTPServer.SessionList but I have not seen if it's possible to use it to get access to each Session data and how to do it safely.
Could you please confirm the comparisons 1, 2 and 3 and provide me with some help on point 4
Regards
(05-28-2020, 10:24 AM)Alan.F Wrote: [ -> ]Based on my experience with TidTCPServer I would like to do the following comparisons :
- with TCPServer we can use the "AContext: TIdContext" to manage authentication and specific client management.
- we can use the onconnect and ondisconnect events at the beginning and at the end.
- we can create a "TMyClient = class(TidServerContext)" to keep memory of the session between each automatic run of the TCPServer OnExecute
- we can use TCPserver.Contexts.Locklist to perform safe operations across active connections (count, send message, .....).
All of those items exist in
TIdHTTPServer as well, since it is a
TIdTCPServer descendant after all (well,
TIdCustomTCPServer, anyway).
However,
TIdContext is per-connection, not per-session. HTTP requests are not restricted to just 1 connection per session.
(05-28-2020, 10:24 AM)Alan.F Wrote: [ -> ]
- there is also HTTPserver.Contexts.Locklist but I don't see any access to the sessions list and there is also the HTTPServer.SessionList but I have not seen if it's possible to use it to get access to each Session data and how to do it safely.
No, HTTP session data is not
directly accessible via
TIdContext, because that is not where the session data belongs.
TIdHTTPRequestInfo and
TIdHTTPResponseInfo have a
Session property instead, since those objects are handled on a per-request basis, regardless of which connection is making each request.
Though, you can type-cast a server-side
TIdContext to
TIdServerContext to access its
Server property, which you can then type-cast to
TIdHTTPServer to access its
SessionList property.
And yes, the
TIdHTTPServer.SessionList is where you can access all of the server's stored session data.
TIdHTTPCustomSessionList has a
GetSession() method, if you know the exact
SessionID and
RemoteIP of a given session. By default, the
TIdHTTPServer.SessionList property points to a
TIdHTTPDefaultSessionList object (if you don't assign your own object), which has its own
SessionList property that is a
TThreadList of
TIdHTTPSession objects (similar to how the
TIdTCPServer.Contexts is a
TThreadList of
TIdContext objects). Or, you can derive your own class from
TIdHTTPCustomSessionList and store session data however you want.
Thanks Remy
I've done the following with success :
Code:
procedure TForm1.IdHTTPServer1SessionStart(Sender: TIdHTTPSession);
begin
Sender.Content.Create;
Sender.Content.AddPair('phase','1');
end;
procedure TForm1.IdHTTPServer1CommandGet(AContext: TIdContext; ARequestInfo: TIdHTTPRequestInfo; AResponseInfo: TIdHTTPResponseInfo);
var
phase : string;
begin
if ARequestInfo.Session <> nil then phase := ARequestInfo.Session.Content.Values['phase'];
....
end;
Concerning the threadlist, with IdHTTPServer1.SessionList I don't see how I can lock the list. Please can you help me ?
(06-03-2020, 02:04 PM)Alan.F Wrote: [ -> ]Code:
procedure TForm1.IdHTTPServer1SessionStart(Sender: TIdHTTPSession);
begin
Sender.Content.Create;
Sender.Content.AddPair('phase','1');
end;
First, that is not the correct syntax to use to create an object.
Second, you don't need to create the
Content object manually anyway, as it is already created for you when the
TIdHTTPSession object is created. So just get rid of that line completely:
Code:
procedure TForm1.IdHTTPServer1SessionStart(Sender: TIdHTTPSession);
begin
Sender.Content.AddPair('phase','1');
end;
(06-03-2020, 02:04 PM)Alan.F Wrote: [ -> ]Code:
procedure TForm1.IdHTTPServer1CommandGet(AContext: TIdContext; ARequestInfo: TIdHTTPRequestInfo; AResponseInfo: TIdHTTPResponseInfo);
var
phase : string;
begin
if ARequestInfo.Session <> nil then phase := ARequestInfo.Session.Content.Values['phase'];
....
end;
That code is fine. You can freely access and set the
ARequestInfo.Session.Content and
AResponseInfo.Session.Content as needed.
(06-03-2020, 02:04 PM)Alan.F Wrote: [ -> ]Concerning the threadlist, with IdHTTPServer1.SessionList I don't see how I can lock the list. Please can you help me ?
As I told you earlier, the
TIdHTTPServer.SessionList property is a
TIdHTTPCustomSessionList, which points to a
TIdHTTPDefaultSessionList by default, and
TIdHTTPDefaultSessionList is where the
TThreadList resides, not in
TIdHTTPCustomSessionList. So, you will have to type-cast the
TIdHTTPServer.SessionList in order to access the
TThreadList, eg:
Code:
var
List: TIdHTTPSessionList;
with (IdHTTPServer1.SessionList as TIdHTTPDefaultSessionList).SessionList do
begin
List := LockList;
try
// use List as needed...
finally
UnlockList;
end;
end;