How Do I setup a Xdata Server for services using Indy. Following the docs to use a indy based server I do the following ..
I need more info about Indy server too, usage of services, database (with DFConnection) and with Echo
This is my attempt to realize the Auth server from TMS Demos with Indy server, but this does not work, I'm got exception "Unknown path LoginService". What I should change to make it worked?
unit uSvc.Module;
interface
procedure StartServer;
implementation
{$R *.dfm}
uses
Bcl.JOSE.Core.Builder,
Bcl.JOSE.Core.JWT,
XData.Service.Common,
XData.Sys.Exceptions,
Aurelius.Drivers.Base,
Aurelius.Drivers.dbExpress,
Sparkle.HttpSys.Config, Sparkle.Indy.Server,
XData.Aurelius.ConnectionPool,
uTypes, uPrgTypes, uLogs,
uDB.Utils;
type
[ServiceContract]
ILoginService = interface(IInvokable)
['{9CFD59B2-A832-4F82-82BB-9A25FC93F305}']
function Login(const User, Password: string): string;
end;
[ServiceImplementation]
TLoginService = class(TInterfacedObject, ILoginService)
public
function Login(const User, Password: string): string;
end;
{ TLoginService }
function TLoginService.Login(const User, Password: string): string;
var
JWT: TJWT;
begin
if User <> Password then
raise EXDataHttpUnauthorized.Create('Invalid password');
JWT := TJWT.Create;
try
JWT.Claims.SetClaimOfType<string>('user', User);
JWT.Claims.SetClaimOfType<boolean>('admin', User = 'admin');
Result := TJOSE.SHA256CompactToken('super_secret', JWT);
finally
JWT.Free;
end;
end;
var
Session: IDBSession;
var
Server: TIndySparkleHTTPServer;
procedure StartServer;
var
ConnFactory: IDBConnectionFactory;
begin
Server := TIndySparkleHTTPServer.Create;
try
Server.DefaultPort := 2001;
ConnFactory := TDBConnectionFactory.Create(
function: IDBConnection
var
Connection: TAureliusConnection;
begin
Connection := TAureliusConnection.Create(nil);
Connection.Params.Values['Database'] := ':memory:';
Connection.Params.Values['EnableForeignKeys'] := 'True';
Connection.DriverName := 'SQLite';
Result := Connection.CreateConnection;
end
);
Server.Dispatcher.AddModule(TXDataServerModule.Create('http://+:2001/tms/auth',
TDBConnectionPool.Create(50, ConnFactory)
));
Server.Active := True;
finally
// Server.Free;
end;
end;
initialization
RegisterServiceType(TLoginService);
end.
Alex, the problem with your code is that you put ILoginService and TLoginService in the implementation section of your unit. This makes them private and Delphi RTTI (and thus XData) can't find them. This is the code you should use:
unit Unit5;
interface
uses
XData.Service.Common;
type
[ServiceContract]
ILoginService = interface(IInvokable)
['{9CFD59B2-A832-4F82-82BB-9A25FC93F305}']
function Login(const User, Password: string): string;
end;
[ServiceImplementation]
TLoginService = class(TInterfacedObject, ILoginService)
public
function Login(const User, Password: string): string;
end;
procedure StartServer;
implementation
uses
Bcl.JOSE.Core.Builder,
Bcl.JOSE.Core.JWT,
XData.Server.Module,
XData.Sys.Exceptions,
Aurelius.Comp.Connection,
Aurelius.Drivers.Base,
Aurelius.Drivers.dbExpress,
Aurelius.Drivers.Interfaces,
Sparkle.HttpSys.Config, Sparkle.Indy.Server,
XData.Aurelius.ConnectionPool;
{ TLoginService }
function TLoginService.Login(const User, Password: string): string;
var
JWT: TJWT;
begin
if User <> Password then
raise EXDataHttpUnauthorized.Create('Invalid password');
JWT := TJWT.Create;
try
JWT.Claims.SetClaimOfType<string>('user', User);
JWT.Claims.SetClaimOfType<boolean>('admin', User = 'admin');
Result := TJOSE.SHA256CompactToken('super_secret', JWT);
finally
JWT.Free;
end;
end;
var
Server: TIndySparkleHTTPServer;
procedure StartServer;
var
ConnFactory: IDBConnectionFactory;
begin
Server := TIndySparkleHTTPServer.Create;
try
Server.DefaultPort := 2001;
ConnFactory := TDBConnectionFactory.Create(
function: IDBConnection
var
Connection: TAureliusConnection;
begin
Connection := TAureliusConnection.Create(nil);
Connection.Params.Values['Database'] := ':memory:';
Connection.Params.Values['EnableForeignKeys'] := 'True';
Connection.DriverName := 'SQLite';
Result := Connection.CreateConnection;
Connection.Free;
end
);
Server.Dispatcher.AddModule(TXDataServerModule.Create('http://+:2001/tms/auth',
TDBConnectionPool.Create(50, ConnFactory)
));
Server.Active := True;
finally
// Server.Free;
end;
end;
initialization
RegisterServiceType(TLoginService);
end.
Wagner R. Landgraf2019-11-27 21:12:21
Phillip, probably you have the same issue? You don't need to call AddServiceImplementation. Just declare your interfaces and classes (ServiceContract and ServiceImplementation), register them in the initialization, and the XData module would automatically detect them.
Thank you very much, that worked, thank you for your answers