Felipe Leal
Felipe Leal

Reputation: 21

Delphi DataSnap Rest

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

Answers (3)

Felipe Leal
Felipe Leal

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

Marc Guillot
Marc Guillot

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

Erwin
Erwin

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

Related Questions