XData Indy server and Services

How Do I setup a Xdata Server for services using Indy. Following the docs to use a indy based server I do the following .. 


procedure TForm1.SetupIndyServer;
var
  Server: TIndySparkleHTTPServer;
  XDataServerModule: TXDataServerModule;
begin
  Server := TIndySparkleHTTPServer.Create(Self);
  Server.DefaultPort := 8080;
  Server.Dispatcher.AddModule(TAnonymousServerModule.Create(
    procedure(const C: THttpServerContext)
    begin
      C.Response.StatusCode := 200;
      C.Response.ContentType := 'text/html';
      C.Response.Close(TEncoding.UTF8.GetBytes('<h1>Hello, World!</h1>'));
    end
  ));

  Server.Active := True;
end;

Works fine when a "hello" service is requested. So to setup the example TMS XData Service I would add ?
   XDataServerModule := TXDataServerModule.create('http://localhost:8080/tms/MyService');
   XDataServerModule.AddServiceImplementation(TMyService);
   Server.Dispatcher.AddModule(XDataServerModule);
but I cant seem to get it to recognise the Sum or Echo services. i.e. I get
Then whats required to enable the SwaggerOptions / SwaggerUIOptions as there doesn't seem to be enabled properties available to the XDataServerModule ?

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