Reputation: 21
I'm running some Datasnap tests with REST and json.
There in Unit ServerMethods, which Delphi itself creates, has the "ReverseString" function, but well, how do I know who sent it?
I would like to keep a log of information from the clients who called this method.
I know it could be passed as a parameter, but it would be the responsibility of the client to pass this information to me, which I do not want, let's say the method would be public and several clients would be triggering this information. I can easily lose this control, if I do not get the information directly by the control of the server.
I found on the web, that in the ServerConteiner unit, has a "DSServer" object, this object has an event called "OnConnect", so it can get the following sa data:
Procedure TServerContainer1.DSServer1Connect (
DSConnectEventObject: TDSConnectEventObject);
Begin
DSConnectEventObject.ChannelInfo.ClientInfo.IpAddress;
DSConnectEventObject.ChannelInfo.ClientInfo.ClientPort;
DSConnectEventObject.ChannelInfo.ClientInfo.Protocol;
DSConnectEventObject.ChannelInfo.ClientInfo.AppName;
End;
But I am not able to find how there in ServerMethods.ReverseString I can get this data ...
I believe that the processing is in thread on the server, so I can not pass this value as global, because it can pick up information from other simultaneous connections.
In the method, ReverseString, I tried as follows:
Var
ADSServerClass: TDSServerClass;
Begin
ADSServerClass: = TDSServerClass (GetOwner);
TDSServer (ADSServerClass.Server). ???
// I got to the server, but I can not find it, and I do not know if it is this way to find the data of who is requesting me to execute the ReverseString
End;
Upvotes: 1
Views: 1965
Reputation: 21
Regards,
solution:
Delphi XE5 Rest Datasnap Server. Getting Client IP Address
var
Session: TDSSession;
Protocol, IpAddress, AppName: string;
begin
Session := TDSSessionManager.GetThreadSession;
Protocol := Session.GetData('CommunicationProtocol');
IpAddress := Session.GetData('RemoteIP');
AppName := Session.GetData('RemoteAppName');
end;
Upvotes: 1
Reputation: 6455
A very dirty solution is to create thread global variables on your ServerContainer
threadvar
IpAddress: string;
ClientPort: integer;
Protocol: string;
AppName: string;
So you can now use these variables and you will see an independent set of values per thread/connection.
The problem of threadvar variables is that there are not emptied when your connection finishes, potentially leading to memory leaks.
So to avoid those leaks you will neeed to clear them manually when your TMethods datamodule is destroyed.
procedure TMyMethods.DataModuleDestroy(Sender: TObject);
begin
if DatabaseCn.Connected then DatabaseCn.Close;
IpAddress := '';
ClientPort := 0;
Protocol := '';
AppName := '';
end;
I'm certain that they are far more elegant solutions, but you could use this alternative if no one else provides a better option.
Upvotes: 0
Reputation: 1926
Server side session management is a solution: an advanced feature of DataSnap. When a client connects to a DataSnap server, a session is created. This session is represented with a TDSSession instance.
In a session object you put for example ip-address. In server method you can read information from session object for specific client connection.
http://docwiki.embarcadero.com/RADStudio/Tokyo/en/Server_Side_Session_Management
Upvotes: 3