logo.png
mORMot2 API Reference

mormot.rest.client.pas unit

Purpose: REpresentation State Tranfer (REST) Types and Classes on Client side
- this unit is a part of the Open Source Synopse mORMot framework 2, licensed under a MPL/GPL/LGPL three license - see LICENSE.md

1.1. Units used in the mormot.rest.client unit

Unit NameDescription
mormot.core.baseFramework Core Shared Types and RTL-like Functions
mormot.core.buffersFramework Core Low-Level Memory Buffer Process
mormot.core.dataFramework Core Low-Level Data Processing Functions
mormot.core.datetimeFramework Core Low-Level Date and Time Support
mormot.core.interfacesFramework Core Low-Level Interface/SOLID Processing
mormot.core.jsonFramework Core Low-Level JSON Processing
mormot.core.logFramework Core Logging
mormot.core.osFramework Core Low-Level Wrappers to the Operating-System API
mormot.core.perfFramework Core Performance and Monitoring Classes
mormot.core.rttiFramework Core Low-Level Cross-Compiler RTTI Definitions
mormot.core.textFramework Core Low-Level Text Processing
mormot.core.threadsFramework Core Multi-Threading Support
mormot.core.unicodeFramework Core Low-Level Unicode UTF-8 UTF-16 Ansi Conversion
mormot.core.variantsFramework Core Low-Level Variants / TDocVariant process
mormot.crypt.coreFramework Core Cryptographic Process (Hashing and Cypher)
mormot.crypt.secureFramework Core Authentication and Security Features
mormot.db.coreDatabase Framework Core Types and Classes
mormot.lib.gssapiLow-level access to the GssApi on Linux/POSIX
mormot.lib.sspiLow-level access to the SSPI/SChannel API for Win32/Win64
mormot.orm.baseObject-Relational-Mapping (ORM) Low-Level Process
mormot.orm.clientORM Types and Classes for the Client side
mormot.orm.coreObject-Relational-Mapping (ORM) Main Types and Classes
mormot.orm.restObject-Relational-Mapping (ORM) Abstract REST Implementation
mormot.rest.coreREpresentation State Tranfer (REST) Core Types and Classes
mormot.soa.clientInterface-based SOA Process Types and Classes for Client-Side
mormot.soa.coreInterface-based SOA Process Core Types and Classes

1.2. mormot.rest.client class hierarchy

TSynPersistentTRestClientCallbacksTRestClientUriTRestClientLibraryRequestTRestTRestClientRoutingTRestClientRoutingRestTRestClientRoutingJsonRpcTObjectTRestClientAuthenticationTRestClientAuthenticationSignedUriTRestClientAuthenticationSspiTRestClientAuthenticationDefaultTRestClientAuthenticationUriTRestClientAuthenticationNoneTRestClientAuthenticationHttpAbstractTRestClientAuthenticationHttpBasicTInterfacedCallbackTBlockingCallbackTInterfacedObjectLocked
mormot.rest.client class hierarchy

1.3. Objects implemented in the mormot.rest.client unit

ObjectsDescription
TBlockingCallbackAsynchrounous callback to emulate a synchronous/blocking process
TInterfacedCallbackTInterfacedObject class which will notify a REST server when it is released
TRestClientAuthenticationAbstract class used to implement client-side authentication
TRestClientAuthenticationDefaultMORMot secure RESTful authentication scheme
TRestClientAuthenticationHttpAbstractAbstract class for implementing HTTP authentication
TRestClientAuthenticationHttpBasicAuthentication using HTTP Basic scheme
TRestClientAuthenticationNoneMORMot weak RESTful authentication scheme
TRestClientAuthenticationSignedUriSecure authentication scheme using URL-level digital signature
TRestClientAuthenticationSspiAuthentication of the current logged user using Windows Security Support Provider Interface (SSPI) or GSSAPI library on Linux
TRestClientAuthenticationUriWeak authentication scheme using URL-level parameter
TRestClientCallbackItemStore information about registered interface callbacks
TRestClientCallbacksStore the references to active interface callbacks on a REST Client
TRestClientLibraryRequestREST client with direct access to a server logic through a .dll/.so library
TRestClientRoutingAbstract Client side service routing
TRestClientRoutingJsonRpcClient calling context using simple REST for interface-based services
TRestClientRoutingRestClient calling context using simple REST for interface-based services
TRestClientSessionStore the information about the current session
TRestClientUriAbstract REpresentational State Transfer (REST) client with URI

1.3.1. TRestClientAuthentication

TRestClientAuthentication = class(TObject)

Abstract class used to implement client-side authentication
- inherit from this class to implement expected authentication scheme


class function ClientSetUser(Sender: TRestClientUri; const aUserName, aPassword: RawUtf8; aPasswordKind: TRestClientSetUserPassword = passClear; const aHashSalt: RawUtf8 = ''; aHashRound: integer = 20000): boolean; virtual;

Class method to be used on client side to create a remote session
- call this method instead of TRestClientUri.SetUser() if you need a custom authentication class
- if saoUserByLogonOrID is defined in the server Options, aUserName may be a TAuthUser.ID and not a TAuthUser.LogonName
- if passClear is used, you may specify aHashSalt and aHashRound, to enable Pbkdf2HmacSha256() use instead of plain Sha256(), and increase security on storage side (reducing brute force attack via rainbow tables)
- will call the ModelRoot/Auth service, i.e. call TRestServer.Auth() published method to create a session for this user
- returns true on success


class procedure ClientSessionSign(Sender: TRestClientUri; var Call: TRestUriParams); virtual; abstract;

Class method to be called on client side to sign an URI
- used by TRestClientUri.Uri()
- shall match the method as expected by RetrieveSession() virtual method


1.3.2. TRestClientAuthenticationUri

TRestClientAuthenticationUri = class(TRestClientAuthentication)

Weak authentication scheme using URL-level parameter


class procedure ClientSessionSign(Sender: TRestClientUri; var Call: TRestUriParams); override;

Class method to be called on client side to add the SessionID to the URI
- append '&session_signature=SessionID' to the url


1.3.3. TRestClientAuthenticationSignedUri

TRestClientAuthenticationSignedUri = class(TRestClientAuthenticationUri)

Secure authentication scheme using URL-level digital signature
- default suaCRC32 format of session_signature is

Hexa8(SessionID)+
Hexa8(Timestamp)+
Hexa8(crc32(SessionID + HexaSessionPrivateKey +
            Sha256('salt' + PassWord) + Hexa8(Timestamp) + url))

class function GetComputeSignature( algo: TRestAuthenticationSignedUriAlgo): TOnRestAuthenticationSignedUriComputeSignature;

Retrieve the method to compute the session_signature=.... value


class procedure ClientSessionSign(Sender: TRestClientUri; var Call: TRestUriParams); override;

Class method to be called on client side to sign an URI
- generate the digital signature as expected by overridden RetrieveSession()
- timestamp resolution is about 256 ms in the current implementation


1.3.4. TRestClientAuthenticationDefault

TRestClientAuthenticationDefault = class(TRestClientAuthenticationSignedUri)

MORMot secure RESTful authentication scheme
- match TRestServerAuthenticationDefault class on server side
- this scheme will use a password stored via safe SHA-256 hashing in the TAuthUser ORM table


1.3.5. TRestClientAuthenticationNone

TRestClientAuthenticationNone = class(TRestClientAuthenticationUri)

MORMot weak RESTful authentication scheme
- this method will authenticate with a given username, but no signature
- match TRestServerAuthenticationNone class on server side
- on client side, this scheme is not called by TRestClientUri.SetUser() method - so you have to write:

 TRestClientAuthenticationNone.ClientSetUser(Client,'User','');

1.3.6. TRestClientAuthenticationHttpAbstract

TRestClientAuthenticationHttpAbstract = class(TRestClientAuthentication)

Abstract class for implementing HTTP authentication
- do not use this abstract class, but e.g. TRestClientAuthenticationHttpBasic
- this class will transmit the session_signature as HTTP cookie, not at URI level, so is expected to be used only from browsers or old clients


class function ClientSetUser(Sender: TRestClientUri; const aUserName, aPassword: RawUtf8; aPasswordKind: TRestClientSetUserPassword = passClear; const aHashSalt: RawUtf8 = ''; aHashRound: integer = 20000): boolean; override;

Class method to be used on client side to create a remote session
- call TRestClientAuthenticationHttpBasic.ClientSetUser() instead of TRestClientUri.SetUser(), and never the method of this abstract class
- needs the plain aPassword, so aPasswordKind should be passClear
- returns true on success


class procedure ClientSessionSign(Sender: TRestClientUri; var Call: TRestUriParams); override;

Class method to be called on client side to sign an URI in Auth Basic resolution is about 256 ms in the current implementation
- set "Cookie: mORMot_session_signature=..." HTTP header


class procedure ClientSetUserHttpOnly(Sender: TRestClientUri; const aUserName, aPasswordClear: RawUtf8); virtual;

Class method to be used on client side to force the HTTP header for the corresponding HTTP authentication, without creating any remote session
- call virtual protected method ComputeAuthenticateHeader()
- here the password should be given as clear content
- potential use case is to use a mORMot client through a HTTPS proxy, e.g. with TRestClientAuthenticationHttpBasic authentication
- then you can use TRestClientAuthentication*.ClientSetUser() to define any another "mORMot only" authentication
- this method is also called by the ClientSetUser() method of this class for a full client + server authentication via HTTP TRestClientAuthenticationHttp*.ClientSetUser()


1.3.7. TRestClientAuthenticationHttpBasic

TRestClientAuthenticationHttpBasic = class(TRestClientAuthenticationHttpAbstract)

Authentication using HTTP Basic scheme
- this protocol send both name and password as clear (just Base64 encoded) so should only be used over TLS / HTTPS, or for compatibility reasons
- match TRestServerAuthenticationHttpBasic class on server side
- will rely on TRestClientAuthenticationNone for authorization
- on client side, this scheme is not called by TRestClientUri.SetUser() method - so you have to write:

 TRestClientAuthenticationHttpBasic.ClientSetUser(Client,'User','password');

- for a remote proxy-only authentication (without creating any mORMot session), you can write:

 TRestClientAuthenticationHttpBasic.ClientSetUserHttpOnly(Client,'proxyUser','proxyPass');

1.3.8. TRestClientAuthenticationSspi

TRestClientAuthenticationSspi = class(TRestClientAuthenticationSignedUri)

Authentication of the current logged user using Windows Security Support Provider Interface (SSPI) or GSSAPI library on Linux
- is able to authenticate the currently logged user on the client side, using either NTLM (Windows only) or Kerberos - it will allow to safely authenticate on a mORMot server without prompting the user to enter its password
- match TRestServerAuthenticationSspi class on server side
- if ClientSetUser() receives aUserName as '', aPassword should be either '' if you expect NTLM authentication to take place, or contain the SPN registration (e.g. 'mymormotservice/myserver.mydomain.tld') for Kerberos authentication
- if ClientSetUser() receives aUserName as 'DomainName\UserName', then authentication will take place on the specified domain, with aPassword as plain password value


1.3.9. TRestClientSession

TRestClientSession = record

Store the information about the current session
- as set after a successful TRestClientUri.SetUser() method


Authentication: TRestClientAuthenticationClass;

For internal use


HeartbeatSeconds: integer;

Frequency of Callback/_ping_ calls to maintain session and services
- will be used to call SessionRenewEvent at the specified period, so that the session and all sicClientDriven instances will be maintained on the server side as long as the client connection stands
- equals half SessionServerTimeout or 25 minutes (if lower) by default - 25 minutes matches the default service timeout of 30 minutes
- you may set 0 to disable this SOA-level heartbeat feature


HttpHeader: RawUtf8;

Access to the low-level HTTP header used for authentication
- you can force here your own header, e.g. a JWT as authentication bearer or as in TRestClientAuthenticationHttpAbstract.ClientSetUserHttpOnlyUser
- used e.g. by TRestClientAuthenticationHttpBasic


ID: cardinal;

The current session ID as set after a successful SetUser() method call
- equals 0 (CONST_AUTHENTICATION_SESSION_NOT_STARTED) if the session is not started yet - i.e. if SetUser() call failed
- equals 1 (CONST_AUTHENTICATION_NOT_USED) if authentication mode is not enabled - i.e. after a fresh Create() without SetUser() call


Server: RawUtf8;

The remote server executable name, as retrieved after a SetUser() success


ServerTimeout: integer;

The remote server session tiemout in minutes, as retrieved after a SetUser() success
- will be used to set SessionHeartbeatSeconds default


User: TAuthUser;

The current user as set by SetUser() method
- contains nil if no User is currently authenticated
- once authenticated, a TAuthUser instance is set, with its ID, LogonName, DisplayName, PasswordHashHexa and GroupRights (filled with a TAuthGroup ID casted as a pointer) properties - you can retrieve any optional binary data associated with this user via RetrieveBlobFields()


Version: RawUtf8;

The remote server version, as retrieved after a SetUser() success


1.3.10. TRestClientRouting

TRestClientRouting = class(TObject)

Abstract Client side service routing
- match TRestServerUriContext reciprocal class
- never use this abstract class, but rather TRestClientRoutingRest or TRestClientRoutingJsonRpc classes


class function Supports: TRestClientSideInvoke; virtual;

Could be overriden to notify advances routing features
- default returns [] but TRestClientRoutingRest includes csiAsOctetStream


class procedure ClientSideInvoke(var uri: RawUtf8; ctxt: TRestClientSideInvoke; const method, params, clientDrivenID: RawUtf8; out sent, head: RawUtf8); virtual; abstract;

At Client Side, compute URI and BODY according to the routing scheme
- abstract implementation which is to be overridden
- as input, method should be the method name to be executed, params should contain the incoming parameters as JSON CSV (without []), and clientDriven ID should contain the optional Client ID value
- at output, should update the HTTP uri corresponding to the proper routing, and should return the corresponding HTTP body/headers within sent/head parameters


class procedure ClientSideInvoked(const uri: RawUtf8; ctxt: TRestClientSideInvoke; const method, params, clientDrivenID: RawUtf8; var resp, head: RawUtf8; var status: integer); virtual;

At Client Side, adjust STATUS and BODY according to the routing scheme
- this method does nothing by default
- could be used to adapt to custom BODY output, e.g. on error handling


1.3.11. TRestClientRoutingRest

TRestClientRoutingRest = class(TRestClientRouting)

Client calling context using simple REST for interface-based services
- match TRestServerRoutingRest reciprocal class


class function Supports: TRestClientSideInvoke; override;

Overriden to include csiAsOctetStream


class procedure ClientSideInvoke(var uri: RawUtf8; ctxt: TRestClientSideInvoke; const method, params, clientDrivenID: RawUtf8; out sent, head: RawUtf8); override;

At Client Side, compute URI and BODY according to RESTful routing scheme
- e.g. on input uri='root/Calculator', method='Add', params='1,2' and clientDrivenID='1234' -> on output uri='root/Calculator.Add/1234' and sent='[1,2]'


1.3.12. TRestClientRoutingJsonRpc

TRestClientRoutingJsonRpc = class(TRestClientRouting)

Client calling context using simple REST for interface-based services
- match TRestServerRoutingJsonRpc reciprocal class


class procedure ClientSideInvoke(var uri: RawUtf8; ctxt: TRestClientSideInvoke; const method, params, clientDrivenID: RawUtf8; out sent, head: RawUtf8); override;

At Client Side, compute URI and BODY according to JSON/RPC routing scheme
- e.g. on input uri='root/Calculator', method='Add', params='1,2' and clientDrivenID='1234' -> on output uri='root/Calculator' and sent={"method":"Add","params":[1,2],"id":1234}


1.3.13. TRestClientCallbackItem

TRestClientCallbackItem = record

Store information about registered interface callbacks


Factory: TInterfaceFactory;

/ information about the associated IInvokable


ID: TRestClientCallbackID;

The identifier of the callback, as sent to the server side
- computed from TRestClientUriCallbacks.fCurrentID counter


Instance: pointer;

Weak pointer typecast to the associated IInvokable variable


ReleasedFromServer: boolean;

Set to TRUE if the instance was released from the server


1.3.14. TRestClientCallbacks

TRestClientCallbacks = class(TSynPersistent)

Store the references to active interface callbacks on a REST Client


Count: integer;

How many callbacks are registered


List: array of TRestClientCallbackItem;

List of registered interface callbacks


Owner: TRestClientUri;

The associated REST instance


constructor Create(aOwner: TRestClientUri); reintroduce;

Initialize the storage list


function DoRegister(aInstance: pointer; aFactory: TInterfaceFactory): TRestClientCallbackID; overload;

Register a callback event interface instance from a new computed ID


function FindAndRelease(aID: TRestClientCallbackID): boolean;

Find a matching entry
- will call FindIndex(aID) within Safe.Lock/Safe.Unlock
- returns TRUE if aID was found and aInstance/aFactory set, FALSE otherwise


function FindEntry(var aItem: TRestClientCallbackItem): boolean;

Find a matching callback
- will call FindIndex(aItem.ID) within Safe.Lock/Safe.Unlock
- returns TRUE if aItem.ID was found and aItem filled, FALSE otherwise


function FindIndex(aID: TRestClientCallbackID): PtrInt;

Find the index of the ID in the internal list
- warning: this method should be called within Safe.Lock/Safe.Unlock


function UnRegister(aInstance: pointer): boolean; overload;

Delete all callback events from the internal list, as specified by its instance
- note that the same IInvokable instance may be registered for several IDs


procedure DoRegister(aID: TRestClientCallbackID; aInstance: pointer; aFactory: TInterfaceFactory); overload;

Register a callback event interface instance from its supplied ID


1.3.15. TRestClientUri

TRestClientUri = class(TRest)

Abstract REpresentational State Transfer (REST) client with URI
- URI are standard Collection/Member implemented as ModelRoot/TableName/TableID
- handle RESTful commands GET POST PUT DELETE LOCK UNLOCK
- never call this abstract class, but inherit and override the InternalUri/InternalIsOpen/InternalOpen/InternalClose virtual abstract methods
- do NOT use this abstract class, but one of its fully implemented children


constructor Create(aModel: TOrmModel); override;

Initialize REST client instance


constructor RegisteredClassCreateFrom(aModel: TOrmModel; aDefinition: TSynConnectionDefinition; aServerHandleAuthentication: boolean); override;

Initialize REST client instance from a TSynConnectionDefinition


destructor Destroy; override;

Release memory and close client connection
- also unlock all still locked records by this client


function CallBack(method: TUriMethod; const aMethodName,aSentData: RawUtf8; out aResponse: RawUtf8; aTable: TOrmClass = nil; aID: TID = 0; aResponseHead: PRawUtf8 = nil): integer;

Wrapper to the protected URI method to call a method on the server, using a ModelRoot/[TableName/[ID/]]MethodName RESTful with any kind of request
- returns the HTTP error code (e.g. 200/HTTP_SUCCESS on success)
- for GET/PUT methods, you should better use CallBackGet/CallBackPut


function CallBackGet(const aMethodName: RawUtf8; const aNameValueParameters: array of const; out aResponse: RawUtf8; aTable: TOrmClass = nil; aID: TID = 0; aResponseHead: PRawUtf8 = nil): integer;

Wrapper to the protected URI method to call a method on the server, using a ModelRoot/[TableName/[ID/]]MethodName RESTful GET request
- returns the HTTP error code (e.g. 200/HTTP_SUCCESS on success)
- this version will use a GET with supplied parameters (which will be encoded with the URL), and append the expected signature (if needed)


function CallBackGetResult(const aMethodName: RawUtf8; const aNameValueParameters: array of const; aTable: TOrmClass = nil; aID: TID = 0): RawUtf8;

Wrapper to the protected URI method to call a method on the server, using a ModelRoot/[TableName/[ID/]]MethodName RESTful GET request
- returns the UTF-8 decoded JSON result (server must reply with one "result":"value" JSON object)
- this version will use a GET with supplied parameters (which will be encoded with the URL), and append the expected signature (if needed)


function CallBackPut(const aMethodName, aSentData: RawUtf8; out aResponse: RawUtf8; aTable: TOrmClass = nil; aID: TID = 0; aResponseHead: PRawUtf8 = nil): integer;

Wrapper to the protected URI method to call a method on the server, using a ModelRoot/[TableName/[ID/]]MethodName RESTful PUT request
- returns the HTTP error code (e.g. 200/HTTP_SUCCESS on success)
- this version will use a PUT with the supplied raw UTF-8 data


function FakeCallbackRegister(Sender: TServiceFactory; const Method: TInterfaceMethod; const ParamInfo: TInterfaceMethodArgument; ParamValue: pointer): TRestClientCallbackID; virtual;

Internal methods used by mormot.soa.client


function GetCurrentSessionUserID: TID; override;

Internal method to retrieve the current Session TAuthUser.ID


function IsOpen: boolean; virtual;

Check if connected to the server, or try to (re)create the connection
- convenient wrapper around InternalIsOpen and InternalOpen virtual methods
- return TRUE on success, FALSE on any connection error
- follows ConnectRetrySeconds property for optional retrial
- calls OnConnected/OnConnectionFailed events if set


function OrmInstance: TRestOrm;

Main access to the class implementing IRestOrm methods for this instance
- used internally to avoid ORM: IRestOrm reference counting and enable inlining of most simple methods, if possible


function Refresh(aID: TID; Value: TOrm; var Refreshed: boolean): boolean;

Backward compatibility redirections to the homonymous IRestOrmClient methods see IRestOrmClient documentation for the proper use information


function ServerRemoteLog(Level: TSynLogLevel; const FormatMsg: RawUtf8; const Args: array of const): boolean; overload;

Internal method able to emulate a call to TSynLog.Add.Log()
- will compute timestamp and event text, than call the overloaded ServerRemoteLog() method


function ServerRemoteLog(Sender: TEchoWriter; Level: TSynLogLevel; const Text: RawUtf8): boolean; overload; virtual;

Asynchronous call a 'RemoteLog' remote logging method on the server
- as implemented by mORMot's LogView tool in server mode
- to be used via ServerRemoteLogStart/ServerRemoteLogStop methods
- a dedicated background thread will run the transmission process without blocking the main program execution, gathering log rows in chunks in case of high activity
- map TOnTextWriterEcho signature, so that you will be able to set e.g.:

 TSqlLog.Family.EchoCustom := aClient.ServerRemoteLog;

function ServerTimestampSynchronize: boolean;

You can call this method to call the remote URI root/Timestamp
- this can be an handy way of testing the connection, since this method is always available, even without authentication
- returns TRUE if the client time correction has been retrieved
- returns FALSE on any connection error - check LastErrorMessage and LastErrorException to find out the exact connection error


function ServiceContainer: TServiceContainer; override;

Access or initialize the internal IoC resolver, used for interface-based remote services, and more generaly any Services.Resolve() call
- create and initialize the internal TServiceContainerClient if no service interface has been registered yet
- may be used to inject some dependencies, which are not interface-based remote services, but internal IoC, without the ServiceRegister() or ServiceDefine() methods - e.g.

 aRest.ServiceContainer.InjectResolver([TInfraRepoUserFactory.Create(aRest)],true);

function ServiceDefine(const aInterfaces: array of TGuid; aInstanceCreation: TServiceInstanceImplementation = sicSingle; const aContractExpected: RawUtf8 = ''): boolean; overload;

Register one or several Services on the client side via their interfaces
- this method expects the interface(s) to have been registered previously:

 TInterfaceFactory.RegisterInterfaces([TypeInfo(IMyInterface),...]);

function ServiceDefine(const aInterface: TGuid; aInstanceCreation: TServiceInstanceImplementation = sicSingle; const aContractExpected: RawUtf8 = ''; aIgnoreAnyException: boolean = true): TServiceFactoryClient; overload;

Register a Service on the client side via its interface
- this method expects the interface to have been registered previously:

 TInterfaceFactory.RegisterInterfaces([TypeInfo(IMyInterface),...]);

function ServiceDefineClientDriven(const aInterface: TGuid; out Obj; const aContractExpected: RawUtf8 = ''): boolean;

Register and retrieve the sicClientDriven Service instance
- this method expects the interface to have been registered previously:

 TInterfaceFactory.RegisterInterfaces([TypeInfo(IMyInterface),...]);

function ServiceDefineSharedApi(const aInterface: TGuid; const aContractExpected: RawUtf8 = SERVICE_CONTRACT_NONE_EXPECTED; aIgnoreAnyException: boolean = false): TServiceFactoryClient;

Register a sicShared Service instance communicating via JSON objects
- will force SERVICE_CONTRACT_NONE_EXPECTED, ParamsAsJsonObject=true and ResultAsJsonObjectWithoutResult=true
- may be used e.g. for accessing a sessionless public REST/JSON API, i.e.

 TRestServer.ServiceDefine(...).ResultAsJsonObjectWithoutResult := true

- this method expects the interface to have been registered previously:

 TInterfaceFactory.RegisterInterfaces([TypeInfo(IMyInterface),...]);

- aIgnoreAnyException may be set to TRUE if the server is likely to not propose this service, and any exception is to be catched


function ServiceRegister(const aInterfaces: array of PRttiInfo; aInstanceCreation: TServiceInstanceImplementation = sicSingle; const aContractExpected: RawUtf8 = ''): boolean; overload; virtual;

Register one or several Services on the client side via their interfaces
- this methods expects a list of interfaces to be registered to the client (e.g. [TypeInfo(IMyInterface)])
- instance implementation pattern will be set by the appropriate parameter
- will return true on success, false if registration failed (e.g. if any of the supplied interfaces is not correct or is not available on the server)
- that is, server side will be called to check for the availability of each interface
- you can specify an optional custom contract for the first interface


function ServiceRegister(aInterface: PRttiInfo; aInstanceCreation: TServiceInstanceImplementation = sicSingle; const aContractExpected: RawUtf8 = ''; aIgnoreAnyException: boolean = true): TServiceFactory; overload;

Register a Service on the client side via its interface
- this methods expects one interface to be registered to the client, as

 Client.ServiceRegister(TypeInfo(IMyInterface),sicShared);

- instance implementation pattern will be set by the appropriate parameter
- will return the corresponding fake class factory on success, nil if registration failed (e.g. if any of supplied interfaces is not correct or is not available on the server)
- that is, server side will be called to check for the availability of each interface
- you can specify an optional custom contract for the first interface


function ServiceRegisterClientDriven(aInterface: PRttiInfo; out Obj; const aContractExpected: RawUtf8 = ''): boolean; overload;

Register and retrieve the sicClientDriven Service instance
- will return TRUE on success, filling Obj output variable with the corresponding interface instance
- will return FALSE on error


function ServiceRetrieveAssociated(const aInterface: TGuid; out URI: TRestServerUriDynArray): boolean; overload;

Return all REST server URI associated to this client, for a given service
- here the service is specified as its TGuid, e.g. IMyInterface
- this method expects the interface to have been registered previously:

 TInterfaceFactory.RegisterInterfaces([TypeInfo(IMyInterface),...]);

- the URI[] output array contains the matching server URIs, the latest registered in first position
- this methods is the reverse from ServicePublishOwnInterfaces: it allows to guess an associated REST server which may implement a given service


function ServiceRetrieveAssociated(const aServiceName: RawUtf8; out URI: TRestServerUriDynArray): boolean; overload;

Return all REST server URI associated to this client, for a given service name, the latest registered in first position
- will lookup for the Interface name without the initial 'I', e.g. 'Calculator' for ICalculator - warning: research is case-sensitive
- this methods is the reverse from ServicePublishOwnInterfaces: it allows to guess an associated REST server which may implement a given service


function SetUser(const aUserName, aPassword: RawUtf8; aHashedPassword: boolean = false): boolean;

Authenticate an User to the current connected Server
- will call the ModelRoot/Auth service, i.e. call TRestServer.Auth() published method to create a session for this user, with our secure TRestClientAuthenticationDefault authentication scheme
- returns true on success
- calling this method is optional, depending on your user right policy: your Server need to handle authentication
- if saoUserByLogonOrID is defined in the server Options, aUserName may be a TAuthUser.ID integer value and not a TAuthUser.LogonName
- on success, the SessionUser property map the logged user session on the server side
- if aHashedPassword is TRUE, the aPassword parameter is expected to contain the already-hashed value, just as stored in PasswordHashHexa (i.e. Sha256('salt'+Value) as in TAuthUser.SetPasswordPlain method)
- if SSPIAUTH conditional is defined, and aUserName='', a Windows authentication will be performed via TRestClientAuthenticationSspi - in this case, aPassword will contain the SPN domain for Kerberos (otherwise NTLM will be used), and table TAuthUser shall contain an entry for the logged Windows user, with the LoginName in form 'DomainName\UserName'
- you can directly create the class method ClientSetUser() of a given TRestClientAuthentication inherited class, if neither TRestClientAuthenticationDefault nor TRestClientAuthenticationSspi match your need


function Uri(const url, method: RawUtf8; Resp: PRawUtf8 = nil; Head: PRawUtf8 = nil; SendData: PRawUtf8 = nil; OutInternalState: PCardinal = nil): integer;

Main method calling the remote Server via a RESTful command
- redirect to the InternalUri() abstract method, which should be overridden for local, pipe, HTTP/1.1 or WebSockets actual communication
- this method will sign the url with the appropriate digital signature according to the current SessionUser property
- this method will retry the connection in case of authentication failure (i.e. if the session was closed by the remote server, for any reason - mostly a time out) if the OnAuthentificationFailed event handler is set


procedure CallbackNonBlockingSetHeader(out Header: RawUtf8); virtual;

To be called before CallBack() if the client could ignore the answer
- do nothing by default, but overriden e.g. in TRestHttpClientWebsockets


procedure DefinitionTo(Definition: TSynConnectionDefinition); override;

Save the TRestClientUri properties into a persistent storage object
- CreateFrom() will expect Definition.UserName/Password to store the credentials which will be used by SetUser()


procedure ServerRemoteLogStart(aLogClass: TSynLogClass; aClientOwnedByFamily: boolean);

Start to send all logs to the server 'RemoteLog' method-based service
- will associate the EchoCustom callback of the running log class to the ServerRemoteLog() method
- if aClientOwnedByFamily is TRUE, this TRestClientUri instance lifetime will be managed by TSynLogFamily - which is mostly wished
- if aClientOwnedByFamily is FALSE, you should manage this instance life time, and may call ServerRemoteLogStop to stop remote logging
- warning: current implementation will disable all logging for this TRestClientUri instance, to avoid any potential concern (e.g. for multi-threaded process, or in case of communication error): you should therefore use this TRestClientUri connection only for the remote log server, e.g. via TRestHttpClientGeneric.CreateForRemoteLogging() - do not call ServerRemoteLogStart() from a high-level business client!


procedure ServerRemoteLogStop;

Stop sending all logs to the server 'RemoteLog' method-based service
- do nothing if aClientOwnedByFamily was TRUE for ServerRemoteLogStart


class procedure ServiceNotificationMethodExecute(var Msg: TMessage);

Event to be triggered when a WM_* message is received from the internal asynchronous notification system, to run the callback in the main UI thread
- WM_* message identifier should have been set e.g. via the associated

 ServiceNotificationMethodViaMessages(Form.Handle, WM_USER)

- message will be sent for any interface-based service method callback which expects no result (i.e. no out parameter nor function result), so is safely handled as asynchronous notification
- is defines as a class procedure, since the underlying TRestClientUri instance has no impact here: a single WM_* handler is enough for several TRestClientUri instances


procedure ServiceNotificationMethodViaMessages(hWnd: HWND; Msg: cardinal);

Set a HWND/WM_* pair to let interface-based services notification callbacks be processed safely in the main UI thread, via Windows messages
- by default callbacks are executed in the transmission thread, e.g. the WebSockets client thread: using UI Synchronize() method may trigger some unexpected race conditions, e.g. when asynchronous notifications are received during a blocking REST command - this message-based mechanism will allow safe and easy notification for any UI client application
- the associated ServiceNotificationMethodExecute() method shall be called in the client HWND TForm for the defined WM_* message


procedure SessionClose;

Clear session and call the /auth service on the server to notify shutdown
- is called by Destroy and SetUser/ClientSetUser methods, so you should not have usually to call this method directly


procedure SetOrmInstance(aORM: TRestOrmParent); override;

Called by TRestOrm.Create overriden constructor to set fOrm from IRestOrm


property Client: IRestOrmClient read fClient;

Main access to the IRestOrmClient methods of this instance


property ComputeSignature: TOnRestAuthenticationSignedUriComputeSignature read fComputeSignature write fComputeSignature;

Customize the session_signature signing algorithm with a specific function
- will be used by TRestServerAuthenticationSignedUri classes, e.g. TRestServerAuthenticationDefault instead of the algorithm specified by the server at session handshake


property ConnectRetrySeconds: integer read fConnectRetrySeconds write fConnectRetrySeconds;

How many seconds the client may try to connect after open socket failure
- is disabled to 0 by default, but you may set some seconds here e.g. to let the server start properly, and let the client handle exceptions to wait and retry until the specified timeout is reached


property LastErrorCode: integer read fLastErrorCode;

Low-level error code, as returned by server
- check this value about HTTP_* constants
- HTTP_SUCCESS or HTTP_CREATED mean no error
- otherwise, check LastErrorMessage property for additional information
- this property value will record status codes returned by Uri() method


property LastErrorException: ExceptClass read fLastErrorException;

Low-level exception class, if any
- will record any Exception class raised within Uri() method
- contains nil if Uri() execution did not raise any exception (which is the most expected behavior, since server-side errors are trapped into LastErrorCode/LastErrorMessage properties


property LastErrorMessage: RawUtf8 read fLastErrorMessage;

Low-level error message, as returned by server
- this property value will record content returned by Uri() method in case of an error, or '' if LastErrorCode is HTTP_SUCCESS or HTTP_CREATED


property MaximumAuthentificationRetry: integer read fMaximumAuthentificationRetry write fMaximumAuthentificationRetry;

Maximum additional retry occurrence
- defaut is 1, i.e. will retry once
- set OnAuthentificationFailed to nil in order to avoid any retry


property OnAfterCall: TOnClientCall read fOnAfterCall write fOnAfterCall;

This Event is called just after the raw InternalUri() method
- the callback could return false to close the connection


property OnAuthentificationFailed: TOnAuthentificationFailed read fOnAuthentificationFailed write fOnAuthentificationFailed;

This Event is called in case of remote authentication failure
- client software can ask the user to enter a password and user name
- if no event is specified, the Uri() method will return directly an HTTP_FORBIDDEN "403 Forbidden" error code


property OnBeforeCall: TOnClientCall read fOnBeforeCall write fOnBeforeCall;

This Event is called just before the raw InternalUri() method
- the callback could return true to continue, or false to abort


property OnConnected: TOnClientNotify read fOnConnected write fOnConnected;

Called by IsOpen when the raw connection is (re)established


property OnConnectionFailed: TOnClientFailed read fOnConnectionFailed write fOnConnectionFailed;

Called by IsOpen when it failed to connect


property OnError: TOnClientCall read fOnError write fOnError;

This Event is called if Uri() was not successful
- the callback could return true to retry the call


property OnFailed: TOnClientFailed read fOnFailed write fOnFailed;

This Event is called if Uri() was not successful
- the callback will have all needed information
- e.g. Call^.OutStatus=HTTP_NOTIMPLEMENTED indicates a broken connection


property OnIdle: TOnIdleSynBackgroundThread read fOnIdle write fOnIdle;

Set a callback event to be executed in loop during remote blocking process, e.g. to refresh the UI during a somewhat long request
- if not set, the request will be executed in the current thread, so may block the User Interface
- you can assign a callback to this property, calling for instance Application.ProcessMessages, to execute the remote request in a background thread, but let the UI still be reactive: the TLoginForm.OnIdleProcess and OnIdleProcessForm methods of mORMotUILogin.pas will match this property expectations


property OnIdleBackgroundThreadActive: boolean read GetOnIdleBackgroundThreadActive;

TRUE if the background thread is active, and OnIdle event is called during process
- to be used e.g. to ensure no re-entrance from User Interface messages


property OnSetUser: TOnClientNotify read fOnSetUser write fOnSetUser;

This Event is called when a user is authenticated
- is called always, on each TRestClientUri.SetUser call
- you can check the Sender.SessionUser property pointing to the current authenticated user, or nil if authentication failed
- could be used to refresh the User Interface layout according to current authenticated user rights, or to subscribe to some services via callbacks


property RetryOnceOnTimeout: boolean read fRetryOnceOnTimeout write fRetryOnceOnTimeout;

If the client shall retry once after "408 REQUEST TIMEOUT" server error
- this is about an HTTP error 408 returned by the server, e.g. when the ORM lock or transaction could not be acquired in a good enough time: this value does not apply to the client side timeout, e.g. at HTTP level


property ServicePublishOwnInterfaces: RawUtf8 read fServicePublishOwnInterfaces write fServicePublishOwnInterfaces;

Allow to notify a server the services this client may be actually capable
- when this client will connect to a remote server to access its services, it will register its own services, supplying its TRestServer instance, and its corresponding public URI, within its '_contract_' internal call
- it will allow automatic service discovery of Peer To Peer Servers, without the need of an actual centralized SOA catalog service: any client could retrieve an associated REST server for a given service, via the ServiceRetrieveAssociated method


property ServiceRoutingSupports: TRestClientSideInvoke read fServiceRoutingSupports;

Direct copy of ServicesRouting.Supports flags


property ServicesRouting: TRestClientRoutingClass read fServicesRouting write SetRoutingClass;

The routing class of the service remote request on client side
- by default, contains TRestClientRoutingRest, i.e. an URI-based layout which is secure (since will use our RESTful authentication scheme), and also very fast
- but TRestClientRoutingJsonRpc can e.g. be set (with TRestServerRoutingJsonRpc on server sides), if the client will rather use JSON/RPC alternative pattern
- NEVER set the abstract TRestClientRouting class on this property


property Session: TRestClientSession read fSession;

The current session information as set by a successful SetUser() call


property SessionHeartbeatSeconds: integer read fSession.HeartbeatSeconds write SetSessionHeartbeatSeconds;

Frequency of Callback/_ping_ calls to maintain session and services
- will be used to call SessionRenewEvent at the specified period, so that the session and all sicClientDriven instances will be maintained on the server side as long as the client connection stands
- equals half SessionServerTimeout or 25 minutes (if lower) by default - 25 minutes matches the default service timeout of 30 minutes
- you may set 0 to disable this SOA-level heartbeat feature


property SessionHttpHeader: RawUtf8 read fSession.HttpHeader write fSession.HttpHeader;

Access to the low-level HTTP header used for authentication
- you can force here your own header, e.g. a JWT as authentication bearer or as in TRestClientAuthenticationHttpAbstract.ClientSetUserHttpOnlyUser


property SessionID: cardinal read fSession.ID;

The current session ID as set after a successful SetUser() method call
- equals 0 (CONST_AUTHENTICATION_SESSION_NOT_STARTED) if the session is not started yet - i.e. if SetUser() call failed
- equals 1 (CONST_AUTHENTICATION_NOT_USED) if authentication mode is not enabled - i.e. after a fresh Create() without SetUser() call


property SessionServer: RawUtf8 read fSession.Server;

The remote server executable name, as retrieved after a SetUser() success


property SessionServerTimeout: integer read fSession.ServerTimeout;

The remote server session tiemout in minutes, as retrieved after a SetUser() success
- will be used to set SessionHeartbeatSeconds default


property SessionUser: TAuthUser read fSession.User;

The current user as set by SetUser() method
- contains nil if no User is currently authenticated


property SessionVersion: RawUtf8 read fSession.Version;

The remote server version, as retrieved after a SetUser() success


1.3.16. TRestClientLibraryRequest

TRestClientLibraryRequest = class(TRestClientUri)

REST client with direct access to a server logic through a .dll/.so library
- use only one TLibraryRequest function for the whole communication
- the data is stored in Global system memory, and freed by GlobalFree()


constructor Create(aModel: TOrmModel; const LibraryName: TFileName); reintroduce; overload;

Connect to a server contained in a shared library
- this .dll/.so must contain at least a LibraryRequest entry
- raise an exception if the shared library is not found or invalid


constructor Create(aModel: TOrmModel; aRequest: TLibraryRequest); reintroduce; overload;

Connect to a server from a remote function


destructor Destroy; override;

Release memory and handles


1.3.17. TInterfacedCallback

TInterfacedCallback = class(TInterfacedObjectLocked)

TInterfacedObject class which will notify a REST server when it is released
- could be used when implementing event callbacks as interfaces, so that the other side instance will be notified when it is destroyed


constructor Create(aRest: TRest; const aGuid: TGuid); reintroduce;

Initialize the instance for a given REST client and callback interface


destructor Destroy; override;

Finalize the instance, and notify the TRestServer that the callback is now unreachable
- i.e. will call CallbackRestUnregister


procedure CallbackRestUnregister; virtual;

Notify the associated TRestServer that the callback is disconnnected
- i.e. will call TRestServer's TServiceContainer.CallBackUnRegister()
- this method will process the unsubscription only once


property Rest: TRest read fRest;

The associated TRestServer instance, which will be notified when the callback is released


property RestInterface: TGuid read fInterface write fInterface;

The interface type, implemented by this callback class


1.3.18. TBlockingCallback

TBlockingCallback = class(TInterfacedCallback)

Asynchrounous callback to emulate a synchronous/blocking process
- once created, process will block via a WaitFor call, which will be released when CallbackFinished() is called by the process background thread


constructor Create(aTimeOutMs: integer; aRest: TRest; const aGuid: TGuid); reintroduce;

Initialize the callback instance
- specify a time out milliseconds period after which blocking execution should be handled as failure (if 0 is set, default 3000 will be used)
- you can optionally set a REST and callback interface for automatic notification when this TInterfacedCallback will be released


destructor Destroy; override;

Finalize the callback instance


function Reset: boolean; virtual;

Just a wrapper to reset the internal Event state to evNone
- may be used to re-use the same TBlockingCallback instance, after a successful WaitFor/CallbackFinished process
- returns TRUE on success (i.e. status was not beWaiting)
- if there is a WaitFor currently in progress, returns FALSE


function WaitFor: TBlockingEvent; virtual;

Called to wait for the callback to be processed, or trigger timeout
- will block until CallbackFinished() is called by the processing thread
- returns the final state of the process, i.e. beRaised or beTimeOut


procedure CallbackFinished(aRestForLog: TRestOrm; aServerUnregister: boolean = false); virtual;

Should be called by the callback when the process is finished
- the caller will then let its WaitFor method return
- if aServerUnregister is TRUE, will also call CallbackRestUnregister to notify the server that the callback is no longer needed
- will optionally log all published properties values to the log class of the supplied REST instance


property Event: TBlockingEvent read GetEvent;

The current state of process
- just a wrapper around Process.Event
- use Reset method to re-use this instance after a WaitFor process


property Process: TBlockingProcess read fProcess;

The associated blocking process instance


1.4. Types implemented in the mormot.rest.client unit

1.4.1. PRestClientCallbackItem

PRestClientCallbackItem = ^TRestClientCallbackItem;

Points to information about registered interface callbacks


1.4.2. TOnAuthentificationFailed

TOnAuthentificationFailed = function(Retry: integer; var aUserName, aPassword: string; out aPasswordHashed: boolean): boolean of object;

Used by TRestClientUri.Uri() to let the client ask for an User name and password, in order to retry authentication to the server
- should return TRUE if aUserName and aPassword both contain some entered values to be sent for remote secure authentication
- should return FALSE if the user pressed cancel or the number of Retry reached a defined limit
- here input/output parameters are defined as plain string, to match the type expected by the client's User Interface, via UI properties, or e.g. from TLoginForm as defined in mORMotUILogin.pas unit


1.4.3. TOnClientCall

TOnClientCall = function(Sender: TRestClientUri; var Call: TRestUriParams): boolean of object;

Called by TRestClientUri.Uri() to notify some step
- e.g. as OnError Event when an error Call.OutStatus was returned
- return false to abort and fail the request
- as OnError with 403, could return true to retry after changing e.g. Sender.SessionHttpHeader with a renewed JWT bearer
- as OnBeforeCall or OnAfterCall, should return true to continue


1.4.4. TOnClientFailed

TOnClientFailed = procedure(Sender: TRestClientUri; E: Exception; Call: PRestUriParams) of object;

Called by TRestClientUri.Uri() when an error occurred
- so that you may have a single entry point for all client-side issues
- information will be available in Sender's LastErrorCode and LastErrorMessage properties
- if the error comes from an Exception, it will be supplied as parameter
- the REST context (if any) will be supplied within the Call parameter, and in this case Call^.OutStatus=HTTP_NOTIMPLEMENTED indicates a broken connection


1.4.5. TOnClientNotify

TOnClientNotify = procedure(Sender: TRestClientUri) of object;

Signature e.g. of the TRestClientUri.OnSetUser event handler


1.4.6. TOnRestAuthenticationSignedUriComputeSignature

TOnRestAuthenticationSignedUriComputeSignature = function( privatesalt: cardinal; timestamp, url: PAnsiChar; urllen: integer): cardinal of object;

Function prototype for TRestClientAuthenticationSignedUri and TRestServerAuthenticationSignedUri computation of the session_signature parameter value


1.4.7. TRestAuthenticationSignedUriAlgo

TRestAuthenticationSignedUriAlgo = ( suaCRC32, suaCRC32C, suaXXHASH, suaMD5, suaSHA1, suaSHA256, suaSHA512, suaSHA3 );

Algorithms known by TRestClientAuthenticationSignedUri and TRestServerAuthenticationSignedUri to digitaly compute the session_signature parameter value for a given URI
- by default, suaCRC32 will compute fast but not cryptographically secure

 crc32(crc32(privatesalt, timestamp, 8), url, urllen)

- suaCRC32C and suaXXHASH are similar non-cryptographic alternatives
- but you can select other stronger alternatives, which result will be reduced to 32-bit hexadecimal - suaMD5 will be the fastest cryptographic hash available on all platforms (but if SHA-NI is available), for enhanced security, by calling e.g.

 (aServer.AuthenticationRegister(TRestClientAuthenticationDefault) as
   TRestServerAuthenticationDefault).Algorithm := suaMD5;

- suaSHA1, suaSHA256, suaSHA512 and suaSHA3 will be slower, and may provide additional level of trust, depending on your requirements: note that since the hash is reduced to 32-bit resolution, those may not provide higher security than suaMD5 or suaSHA1
- note that SynCrossPlatformRest clients only implements suaCRC32 yet


1.4.8. TRestClientAuthenticationClass

TRestClientAuthenticationClass = class of TRestClientAuthentication;

Class-reference type (metaclass) used to define an authentication scheme


1.4.9. TRestClientCallbackID

TRestClientCallbackID = type integer;

31-bit positive identifier of an interface callback, as sent to the server


1.4.10. TRestClientRoutingClass

TRestClientRoutingClass = class of TRestClientRouting;

Class used to define the Client side expected routing
- match TRestServerUriContextClass reciprocal meta-class
- most of the internal methods are declared as virtual, so it allows any kind of custom routing or execution scheme
- TRestClientRoutingRest and TRestClientRoutingJsonRpc classes are provided in this unit, to allow RESTful and JSON/RPC protocols on Client side
- you can retrieve the client class from the reciprocal server-side class using TRestServerUriContext.ClientRouting class method


1.4.11. TRestClientSetUserPassword

TRestClientSetUserPassword = ( passClear, passHashed, passKerberosSpn );

Define how TRestClientAuthentication.ClientSetUser() should interpret the supplied password
- passClear means that the password is not encrypted, e.g. as entered by the user in the login screen
- passHashed means that the passwod is already hashed as in TAuthUser.PasswordHashHexa i.e. Sha256('salt'+Value)
- passKerberosSpn indicates that the password is the Kerberos SPN domain


1.4.12. TRestClientSideInvoke

TRestClientSideInvoke = set of ( csiAsOctetStream);

/ used to customize TRestClientRouting.ClientSideInvoke process


1.4.13. TSqlRestClientUri

TSqlRestClientUri = TRestClientUri;

Backward compatibility types redirections


1.4.14. TSqlRestServerAuthenticationClientSetUserPassword

TSqlRestServerAuthenticationClientSetUserPassword = TRestClientSetUserPassword;

Backward compatibility types redirections


1.4.15. TSqlRestServerUriContextClientInvoke

TSqlRestServerUriContextClientInvoke = TRestClientSideInvoke;

Backward compatibility types redirections