
Purpose: REpresentation State Tranfer (REST) Types and Classes on Server 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
| Unit Name | Description | |
|---|---|---|
| mormot.core.base | Framework Core Shared Types and RTL-like Functions | |
| mormot.core.buffers | Framework Core Low-Level Memory Buffer Process | |
| mormot.core.data | Framework Core Low-Level Data Processing Functions | |
| mormot.core.datetime | Framework Core Low-Level Date and Time Support | |
| mormot.core.interfaces | Framework Core Low-Level Interface/SOLID Processing | |
| mormot.core.json | Framework Core Low-Level JSON Processing | |
| mormot.core.log | Framework Core Logging | |
| mormot.core.os | Framework Core Low-Level Wrappers to the Operating-System API | |
| mormot.core.perf | Framework Core Performance and Monitoring Classes | |
| mormot.core.rtti | Framework Core Low-Level Cross-Compiler RTTI Definitions | |
| mormot.core.text | Framework Core Low-Level Text Processing | |
| mormot.core.threads | Framework Core Multi-Threading Support | |
| mormot.core.unicode | Framework Core Low-Level Unicode UTF-8 UTF-16 Ansi Conversion | |
| mormot.core.variants | Framework Core Low-Level Variants / TDocVariant process | |
| mormot.crypt.core | Framework Core Cryptographic Process (Hashing and Cypher) | |
| mormot.crypt.jwt | Framework Core JSON Web Tokens (JWT) Support | |
| mormot.crypt.secure | Framework Core Authentication and Security Features | |
| mormot.db.core | Database Framework Core Types and Classes | |
| mormot.lib.gssapi | Low-level access to the GssApi on Linux/POSIX | |
| mormot.lib.sspi | Low-level access to the SSPI/SChannel API for Win32/Win64 | |
| mormot.orm.base | Object-Relational-Mapping (ORM) Low-Level Process | |
| mormot.orm.core | Object-Relational-Mapping (ORM) Main Types and Classes | |
| mormot.orm.rest | Object-Relational-Mapping (ORM) Abstract REST Implementation | |
| mormot.orm.server | ORM Types and Classes for the Server side | |
| mormot.orm.storage | ORM Types and Classes for the Server side JSON/Binary Storage | |
| mormot.rest.client | REpresentation State Tranfer (REST) Types and Classes on Client side | |
| mormot.rest.core | REpresentation State Tranfer (REST) Core Types and Classes | |
| mormot.soa.core | Interface-based SOA Process Core Types and Classes | |
| mormot.soa.server | Interface-based SOA Process Types and Classes for Server-Side |
| Objects | Description | |
|---|---|---|
| EParsingException | Exception raised in case of unexpected parsing error | |
| ERestTree | Exception class raised during TRestTree URI parsing | |
| ESecurityException | Exception raised when security authorization/authentication failed | |
| TAuthSession | Class used to maintain in-memory sessions | |
| TAuthSessionParent | Used for efficient TAuthSession.IDCardinal comparison | |
| TOrmMonitorUsage | ORM table used to store TSynMonitorUsage information in TSynMonitorUsageRest | |
| TRestHttpServerDefinition | Parameters supplied to publish a TRestServer via HTTP | |
| TRestRouter | Efficient server-side URI routing for TRestServer | |
| TRestServer | Abstract REpresentational State Transfer (REST) server | |
| TRestServerAuthentication | Abstract class used to implement server-side authentication in TRestServer | |
| TRestServerAuthenticationDefault | MORMot secure RESTful authentication scheme on Server | |
| TRestServerAuthenticationHttpAbstract | Abstract class for implementing HTTP authentication | |
| TRestServerAuthenticationHttpBasic | Authentication using HTTP Basic scheme | |
| TRestServerAuthenticationNone | MORMot weak RESTful authentication scheme | |
| TRestServerAuthenticationSignedUri | Secure authentication scheme using URL-level digital signature | |
| TRestServerAuthenticationSspi | Authentication of the current logged user using Windows Security Support Provider Interface (SSPI) or the GSSAPI library on Linux | |
| TRestServerAuthenticationUri | Weak authentication scheme using URL-level parameter | |
| TRestServerMethod | Description of a method-based service | |
| TRestServerMonitor | Used for high-level statistics in TRestServer.Uri() | |
| TRestServerRoutingJsonRpc | Calling context for a TOnRestServerCallBack using JSON/RPC for interface-based services | |
| TRestServerRoutingRest | Calling context for a TOnRestServerCallBack using our default simple REST routing for interface-based services | |
| TRestServerUriContext | Abstract calling context for a TOnRestServerCallBack event handler | |
| TRestServerUriPagingParameters | Structure used to specify custom request paging parameters for TRestServer | |
| TRestTreeNode | Implement a Radix Tree node to hold one URI registration | |
| TRestTreeNodeData | REST-specific context information, as stored in TRestTreeNode | |
| TServiceRunningContext | Will identify the currently running service on the server side | |
| TSynMonitorUsageRest | Will store TSynMonitorUsage information in TOrmMonitorUsage ORM tables |
EParsingException = class(ESynException)
Exception raised in case of unexpected parsing error
ESecurityException = class(ESynException)
Exception raised when security authorization/authentication failed
TServiceRunningContext = record
Will identify the currently running service on the server side
- is the type of the ServiceRunningContext per-thread function
- to access the current TRestServer instance (and e.g. its ORM/CRUD or SOA methods), use Request.Server and not Factory.Server, which may not be available e.g. if you run the service from the server side (so no factory is involved)
- note that the safest (and slightly faster) access to the TRestServer instance associated with a service is to inherit your implementation class from TInjectableObjectRest
- should map TPerThreadRunningContext private version in mormot.core.interfaces.pas
Factory: TServiceFactory;
The currently running TServiceFactoryServer instance
- it can be used within server-side implementation to retrieve the associated TRestServer instance
- note that TServiceFactoryServer.Get() won't override this value, when called within another service (i.e. if Factory is not nil)
Request: TRestServerUriContext;
The currently runnning context which launched the method
- low-level RESTful context is also available in its Call member
- Request.Server is the safe access point to the underlying TRestServer, unless the service is implemented via TInjectableObjectRest, so the TInjectableObjectRest.Server property is preferred
- make available e.g. current session or authentication parameters (including e.g. user details via Request.Server.SessionGetUser)
RunningThread: TThread;
The thread which launched the request
- is set by TRestServer.BeginCurrentThread from multi-thread server handlers - e.g. TRestHttpServer
TRestServerUriContext = class(TRestUriContext)
Abstract calling context for a TOnRestServerCallBack event handler
- having a dedicated class avoid changing the implementation methods signature if the framework add some parameters or behavior to it
- see TOnRestServerCallBack for general code use
- most of the internal methods are declared as virtual, so it allows any kind of custom routing or execution scheme
- instantiated by the TRestServer.Uri() method using its ServicesRouting property
- see TRestServerRoutingRest and TRestServerRoutingJsonRpc for workable classes - this abstract class will be rejected for TRest.ServicesRouting
- on client side, see TRestClientRouting reciprocal class hierarchy and the ClientRouting class method - as defined in mormot.rest.client.pas
destructor Destroy; override;
Finalize the execution context
function AuthenticationBearerToken: RawUtf8; override;
Method overriden to support rsoAuthenticationUriDisable option
- i.e. as an alternative, a non-standard and slightly less safe way of token transmission may be to encode its value as ?authenticationbearer=.... URI parameter (may be convenient when embedding resources in HTML DOM - but note that the URI is usually part of the web server logs, so it may be unsafe to use it on production - but may be handy e.g. for debugging or if you can't tweak the HTTP headers - as with websockets on JavaScript)
function AuthenticationCheck(jwt: TJwtAbstract): boolean; override;
Validate "Authorization: Bearer <JWT>" content from incoming HTTP headers
- overriden to support TRestServer.JwtForUnauthenticatedRequestWhiteIP()
function CanExecuteOrmWrite(Method: TUriMethod; Table: TOrmClass; TableIndex: integer; const TableID: TID; const Rights: TOrmAccessRights): boolean;
Validate mPOST/mPUT/mDELETE action against current session access rights
- used by TRestServerUriContext.ExecuteOrmWrite and TRestServer.EngineBatchSend methods for proper security checks
function ClientOrmOptions: TOrmWriterOptions;
Identify if the request is about a Table containing nested objects or arrays, which could be serialized as JSON objects or arrays, instead of plain JSON string (as stored in the database)
- will idenfity ClientKind=ckAjax, or check for rsoGetAsJsonNotAsString in TRestServer.Options
class function ClientRouting: TRestClientRoutingClass; virtual;
The associated routing class on the client side
function GetInputAsTDocVariant(const Options: TDocVariantOptions; InterfaceMethod: PInterfaceMethod): variant;
Retrieve all input parameters from URI as a variant JSON object
- returns Unassigned if no parameter was defined
- returns a JSON object with input parameters encoded as
{"name1":value1,"name2":value2...}- optionally with a PInterfaceMethod information about the actual values types
- if the parameters were encoded as multipart, the JSON object will be encoded with its textual values, or with nested objects, if the data was supplied as binary:
{"name1":{"data":..,"filename":...,"contenttype":...},"name2":...}since name1.data will be Base64 encoded, so you should better use the InputAsMultiPart() method instead when working with binary
function InputEnum(const ParamName: RawUtf8; EnumType: PRttiInfo; out ValueEnum; DefaultEnumOrd: integer = 0): boolean;
Retrieve one input parameter from its URI name as an enumeration
- will expect the value to be specified as integer, or as the textual representation of the enumerate, ignoring any optional lowercase prefix as featured by TEnumType.GetEnumNameValue()
- returns TRUE and set ValueEnum if the parameter is found and correct
- returns FALSE and set ValueEnum to first item (i.e. DefaultEnumOrd) if the parameter is not found, or not containing a correct value
function InputOrError(const ParamName: RawUtf8; out Value: variant; const ErrorMessageForMissingParameter: string): boolean;
Retrieve one input parameter from its URI name as variant
- returns FALSE and call Error(ErrorMessageForMissingParameter) - which may be a resourcestring - if the parameter is not found
- returns TRUE and set Value if the parameter is found
- if the parameter value is text, it is stored in the variant as a RawUtf8: so before Delphi 2009, you won't loose any Unicode character, but you should convert its value to AnsiString using Utf8ToString()
function InputUtf8OrDefault(const ParamName, DefaultValue: RawUtf8): RawUtf8;
Retrieve one input parameter from its URI name as RawUtf8
- returns supplied DefaultValue if the parameter is not found
function InputUtf8OrError(const ParamName: RawUtf8; out Value: RawUtf8; const ErrorMessageForMissingParameter: string = ''): boolean;
Retrieve one input parameter from its URI name as RawUtf8
- returns FALSE and call Error(ErrorMessageForMissingParameter) - which may be a resourcestring - if the parameter is not found; if ErrorMessageForMissingParameter is not set, a default message is used
- returns TRUE and set Value if the parameter is found
function IsRemoteAdministrationExecute: boolean;
True if called from TRestServer.AdministrationExecute
function UriWithoutInlinedParams: shortstring;
Same as Call^.Uri, but without the ?... ending
- will compute it from Call^.Url and fParameters
- since used for logging, return a shortstring and not a RawUtf8 to avoid memory allocation
function UriWithoutRoot: RawUtf8;
Same as Call^.Uri, after the 'root/' prefix, including '?' params
- will compute it from Call^.Url and Server.Model.RootLen
function UriWithoutSignature: RawUtf8;
Same as Call^.Uri, but without the &session_signature=... ending
- will compute it from Call^.Url and UriSessionSignaturePos
procedure AuthenticationFailed(Reason: TOnAuthenticationFailedReason); virtual;
Method called in case of authentication failure
- the failure origin is stated by the Reason parameter
- this default implementation will just set OutStatus := HTTP_FORBIDDEN and call TRestServer.OnAuthenticationFailed event (if any)
- is used internally
procedure ConfigurationRestMethod(SettingsStorage: TObject);
Implements a method-based service for live update of some settings
- should be called from a method-based service, e.g. Configuration()
- the settings are expected to be stored e.g. in a TSynAutoCreateFields instance, potentially with nested objects
- accept the following REST methods to read and write the settings:
GET http://server:888/root/configuration GET http://server:888/root/configuration/propname GET http://server:888/root/configuration/propname?value=propvalue
- could be used e.g. as such:
procedure TMyRestServerMethods.Configuration(Ctxt: TRestServerUriContext); begin // http://server:888/myrestserver/configuration/name?value=newValue Ctxt.ConfigurationRestMethod(fSettings); end;
procedure Error(const ErrorMessage: RawUtf8 = ''; Status: integer = HTTP_BADREQUEST; CacheControlMaxAgeSec: integer = 0); override;
Use this method to send back an error to the caller
- overriden method with additional logging
procedure ExecuteCallback(var Ctxt: TJsonParserContext; ParamInterfaceInfo: TRttiJson; out Obj); virtual;
Event raised by ExecuteMethod() for interface parameters
- match TInterfaceMethodInternalExecuteCallback signature
- redirect to TServiceContainerServer.GetFakeCallback
procedure FillInput(const LogInputIdent: RawUtf8 = '');
Extract the input parameters from its URI (up to 512 params)
- you should not have to call this method directly, but rather all the InputInt/InputDouble/InputUtf8/InputExists/... properties
- may be useful if you want to access directly to InputPairs[] with no prior knowledge of the input parameter names
- you can specify a title text to optionally log the input array
procedure LogFromContext;
Low-level logging after service execution
procedure OutHeadFromCookie; override;
Low-level HTTP header merge of the OutSetCookie value
- this overriden method will handle rsoCookieIncludeRootPath option
procedure Prepare(aServer: TRestServer; const aCall: TRestUriParams); virtual;
Initialize the execution context
- this method could have been declared as protected, since it should never be called outside the TRestServer.Uri() method workflow
- should set Call, and Method members
procedure ReturnFileFromFolder(const FolderName: TFileName; Handle304NotModified: boolean = true; const DefaultFileName: TFileName = 'index.html'; const Error404Redirect: RawUtf8 = ''; CacheControlMaxAgeSec: integer = 0); override;
Use this method to send back a file from a local folder to the caller
- UriMethodPath value, as parsed from the URI, will contain the expected file name in the local folder, using DefaultFileName if the URI is void, and redirecting to Error404Redirect if the file is not found
procedure ServiceResult(const Name, JsonValue: RawUtf8);
Low-level process of the JSON result for a service execution
procedure ServiceResultEnd(WR: TJsonWriter; ID: TID); virtual;
Low-level closure of the JSON result for a service execution
procedure ServiceResultStart(WR: TJsonWriter); virtual;
Low-level preparation of the JSON result for a service execution
procedure StatsFromContext(Stats: TSynMonitorInputOutput; MicroSec: Int64);
Low-level statistics merge during service execution
property AuthSession: TAuthSession read fAuthSession write fAuthSession;
Low-level access to the associated Session
- may be nil depending on the context: you should NOT use it, but the safe Session, SessionGroup, SessionUser, SessionUserName fields instead
- is used internally
property Command: TRestServerUriContextCommand read fCommand;
The current execution command
property CustomErrorMsg: RawUtf8 read fCustomErrorMsg;
Optional error message which will be transmitted as JSON error (if set)
- contains e.g. TOnAuthenticationFailedReason text during TRestServer.OnAuthenticationFailed event call, or the reason of a TRestServer.RecordCanBeUpdated failure
property ForceServiceResultAsJsonObject: boolean read fForceServiceResultAsJsonObject;
Force the interface-based service methods to return a JSON object
- default behavior is to follow Service.ResultAsJsonObject property value (which own default is to return a more convenient JSON array)
- if set to TRUE, this execution context will FORCE the method to return a JSON object, even if Service.ResultAsJsonObject=false: this may be handy when the method is executed from a JavaScript content
property ForceServiceResultAsJsonObjectWithoutResult: boolean read fForceServiceResultAsJsonObjectWithoutResult;
Force the interface-based service methods to return a plain JSON object
- i.e. '{....}' instead of '{"result":{....}}'
- only set if ForceServiceResultAsJsonObject=TRUE and if no ID is about to be returned
- could be used e.g. for stateless interaction with a (non mORMot) stateless JSON REST Server
property ForceServiceResultAsXMLObject: boolean read fForceServiceResultAsXMLObject;
Force the interface-based service methods to return a XML object
- default behavior is to follow Service.ResultAsJsonObject property value (which own default is to return a more convenient JSON array)
- if set to TRUE, this execution context will FORCE the method to return a XML object, by setting ForceServiceResultAsJsonObject then converting the resulting JSON object into the corresponding XML via JsonBufferToXML()
- TRestServerUriContext.InternalExecuteSoaByInterface will inspect the Accept HTTP header to check if the answer should be XML rather than JSON
property ForceServiceResultAsXMLObjectNameSpace: RawUtf8 read fForceServiceResultAsXMLObjectNameSpace;
Specify a custom name space content when returning a XML object
- default behavior is to follow Service.ResultAsXMLObjectNameSpace property (which is void by default)
- service may set e.g. XMLUTF8_NAMESPACE, which will append <content ...> </content> around the generated XML data, to avoid validation problems or set a particular XML name space, depending on the application
property Input[const ParamName: RawUtf8]: variant read GetInput;
Retrieve one input parameter from its URI name as variant
- if the parameter value is text, it is stored in the variant as a RTL string content: so before Delphi 2009, you may loose some characters at decoding from UTF-8 input buffer
- raise an EParsingException if the parameter is not found
property InputAllowDouble: boolean read fInputAllowDouble write fInputAllowDouble;
If Input[] InputOrVoid[] InputOrError() variants could be double
property InputDouble[const ParamName: RawUtf8]: double read GetInputDouble;
Retrieve one input parameter from its URI name as double
- raise an EParsingException if the parameter is not found
property InputDoubleOrVoid[const ParamName: RawUtf8]: double read GetInputDoubleOrVoid;
Retrieve one input parameter from its URI name as double
- returns 0 if the parameter is not found
property InputExists[const ParamName: RawUtf8]: boolean read GetInputExists;
Return TRUE if the input parameter is available at URI
- even if InputUtf8['param']='', there may be '..?param=&another=2'
property InputHexaOrVoid[const ParamName: RawUtf8]: cardinal read GetInputHexaOrVoid;
Retrieve one hexadecimal input parameter from its URI name as cardinal
- returns 0 if the parameter is not found
property InputInt[const ParamName: RawUtf8]: Int64 read GetInputInt;
Retrieve one input parameter from its URI name as Int64
- raise an EParsingException if the parameter is not found
property InputIntOrVoid[const ParamName: RawUtf8]: Int64 read GetInputIntOrVoid;
Retrieve one input parameter from its URI name as Int64
- returns 0 if the parameter is not found
property InputOrVoid[const ParamName: RawUtf8]: variant read GetInputOrVoid;
Retrieve one input parameter from its URI name as variant
- if the parameter value is text, it is stored in the variant as a RawUtf8: so before Delphi 2009, you won't loose any Unicode character, but you should convert its value to AnsiString using Utf8ToString()
- returns Unassigned if the parameter is not found
property InputPairs: TRawUtf8DynArray read fInput;
Low-level access to the input parameters, stored as pairs of UTF-8
- even items are parameter names, odd are values
- Input*[] properties should have been called previously to fill the internal array, or by calling FillInput if you do not know the input parameters which may appear
property InputString[const ParamName: RawUtf8]: string read GetInputString;
Retrieve one input parameter from its URI name as a RTL string
- raise an EParsingException if the parameter is not found
- prior to Delphi 2009, some Unicode characters may be missing in the returned AnsiString value
property InputStringOrVoid[const ParamName: RawUtf8]: string read GetInputStringOrVoid;
Retrieve one input parameter from its URI name as a RTL string
- returns '' if the parameter is not found
- prior to Delphi 2009, some Unicode characters may be missing in the returned AnsiString value
property InputUtf8[const ParamName: RawUtf8]: RawUtf8 read GetInputUtf8;
Retrieve one input parameter from its URI name as RawUtf8
- raise an EParsingException if the parameter is not found
property InputUtf8OrVoid[const ParamName: RawUtf8]: RawUtf8 read GetInputUtf8OrVoid;
Retrieve one input parameter from its URI name as RawUtf8
- returns '' if the parameter is not found
property Log: TSynLog read fLog;
Associated logging instance for the current thread on the server
- you can use it to log some process on the server side
property MethodIndex: integer read fMethodIndex;
The index of the callback published method within the internal class list
property MicroSecondsElapsed: QWord read fMicroSecondsElapsed;
High-resolution timimg of the execution command, in micro-seconds
- only set when TRestServer.Uri finished, available e.g. for OnAfterUri
property MicroSecondsStart: Int64 read fMicroSecondsStart;
High-resolution start of the execution command, in micro-seconds
property Parameters: PUtf8Char read fParameters;
URI inlined parameters position within Call^.Url, just after trailing '?'
- use UrlDecodeValue*() functions to retrieve the values
- for mPOST requests, will also be filled from a WEB form body, i.e.
application/x-www-form-urlencoded
- use InputAsMultiPart() for multipart/form-data decoding
property ResourceFileName: TFileName read GetResourceFileName;
Compute the file name corresponding to the URI
- e.g. '/root/methodname/toto/index.html' will return 'toto\index.html'
property Server: TRestServer read fServer;
The associated TRestServer instance which executes its URI method
property Service: TServiceFactory read fService write fService;
The service identified by an interface-based URI
- is in fact a TServiceFactoryServer instance
property ServiceExecution: PServiceFactoryExecution read fServiceExecution write fServiceExecution;
The current execution context of an interface-based service
- maps to
Service.fExecution[ServiceMethodIndex - SERVICE_PSEUDO_METHOD_COUNT]
property ServiceExecutionOptions: TInterfaceMethodOptions read fServiceExecutionOptions write fServiceExecutionOptions;
The current execution options of an interface-based service
- contains a local copy of ServiceExecution.Options, adding eventual optNoLogInput/optNoLogOutput for TInterfaceFactory.RegisterUnsafeSpiType
property ServiceInstanceID: TID read fServiceInstanceID write fServiceInstanceID;
The instance ID for interface-based services instance
- can be e.g. the sicPerSession session ID, the sicPerThread thread ID, or the sicClientDriven field as decoded by UriDecodeSoaByInterface
property ServiceMethod: PInterfaceMethod read fServiceMethod write fServiceMethod;
Access to the raw information of an interface-based URI
- equals nil if ServiceMethodIndex is within 0..3 (pseudo-methods)
property ServiceMethodIndex: integer read fServiceMethodIndex write fServiceMethodIndex;
The method index for an interface-based service
- filled if Service is not nil
- as retrieved by Service.ServiceMethodIndex(), i.e. 0..3 as internal _free_/_contract_/_signature_/_instance_ pseudo-methods or in InterfaceFactory.Methods[ServiceMethodIndex-SERVICE_PSEUDO_METHOD_COUNT]
property ServiceParameters: PUtf8Char read fServiceParameters write fServiceParameters;
The JSON array of parameters for an the interface-based service
- Service member has already be retrieved from URI (so is not nil)
property Session: cardinal read fSession write fSession;
The corresponding session TAuthSession.IDCardinal value
- equals 0 (CONST_AUTHENTICATION_SESSION_NOT_STARTED) if the session is not started yet - i.e. if still in handshaking phase
- equals 1 (CONST_AUTHENTICATION_NOT_USED) if authentication mode is not enabled - i.e. if TRestServer.HandleAuthentication = FALSE
property SessionGroup: TID read fSessionGroup write fSessionGroup;
The corresponding TAuthSession.User.GroupRights.ID value
- is undefined if Session is 0 or 1 (no authentication running)
property SessionOS: TOperatingSystemVersion read fSessionOS write fSessionOS;
The corresponding TAuthSession.RemoteOsVersion
- is undefined if Session is 0 or 1 (no authentication running) or if the client was not using TRestClientAuthenticationDefault scheme
property SessionUser: TID read fSessionUser write fSessionUser;
The corresponding TAuthSession.User.ID value
- is undefined if Session is 0 or 1 (no authentication running)
property SessionUserName: RawUtf8 read fSessionUserName write fSessionUserName;
The corresponding TAuthSession.User.LogonName value
- is undefined if Session is 0 or 1 (no authentication running)
property StaticKind: TRestServerKind read fStaticKind;
The kind of static instance corresponding to the associated Table (if any)
property StaticOrm: TRestOrm read fStaticOrm;
The static instance corresponding to the associated Table (if any)
property Table: TOrmClass read fTable;
The Table as specified at the URI level (if any)
property TableEngine: TRestOrm read fTableEngine;
The RESTful instance implementing the Table specified at the URI level (if any)
- equals the Server field most of the time, but may be an TRestStorage for any in-memory/MongoDB/virtual instance
property TableID: TID read fTableID;
The associated TOrm.ID, as decoded from URI scheme
- this property will be set from incoming URI, even if RESTful authentication is not enabled
property TableIndex: integer read fTableIndex;
The index in the Model of the Table specified at the URI level (if any)
property TableModelProps: TOrmModelProperties read fTableModelProps;
The RTTI properties of the Table specified at the URI level (if any)
property ThreadServer: PServiceRunningContext read fThreadServer;
Just a wrapper over ServiceRunningContext function result
- avoid a call to the threadvar resolution
property UriBlobFieldName: RawUtf8 read fUriMethodPath;
May be used in old method-based service callbacks
property UriMethodPath: RawUtf8 read fUriMethodPath;
The URI after the method service name, excluding the '?' parameters
- as set by TRestTreeNode.LookupParam from <path:fulluri> place holder
property UriSessionSignaturePos: integer read fUriSessionSignaturePos;
Position of the &session_signature=... text in Call^.Url string
TRestServerMethod = record
Description of a method-based service
ByPassAuthentication: boolean;
Set to TRUE disable Authentication check for this method
- use TRestServer.ServiceMethodByPassAuthentication() method
CallBack: TOnRestServerCallBack;
The event which will be executed for this method
Methods: TUriMethods;
The allowed HTTP methods on this service
Name: RawUtf8;
The method name
Stats: TSynMonitorInputOutput;
Detailed statistics associated with this method
TRestServerRoutingJsonRpc = class(TRestServerUriContext)
Calling context for a TOnRestServerCallBack using JSON/RPC for interface-based services
- see also TRestClientRoutingRest alternative (and default) class
- in this routing scheme, the URI will define the interface, then the method name will be inlined with parameters, e.g.
POST /root/Calculator
(...)
{"method":"Add","params":[1,2]}or, for a sicClientDriven mode service:
POST /root/ComplexNumber
(...)
{"method":"Add","params":[20,30],"id":1234}class function ClientRouting: TRestClientRoutingClass; override;
The associated routing class on the client side
- this overriden method returns TRestClientRoutingJsonRpc
TRestServerRoutingRest = class(TRestServerUriContext)
Calling context for a TOnRestServerCallBack using our default simple REST routing for interface-based services
- see also TRestClientRoutingJsonRpc alternative class
- this class will use RESTful routing for interface-based services: method name will be identified within the URI, as
/Model/Interface.Method[/ClientDrivenID]
e.g. for ICalculator.Add:
POST /root/Calculator.Add (...) [1,2]
or, for a sicClientDriven mode service:
POST /root/ComplexNumber.Add/1234 (...) [20,30]
in this case, the sent content will be a JSON array of [parameters...]
- as an alternative, input parameters may be encoded at URI level (with a size limit depending on the HTTP routers, whereas there is no such limitation when they are transmitted as message body)
- one benefit of having .../ClientDrivenID encoded at URI is that it will be more secured in our RESTful authentication scheme: each method and even client driven session will be signed individualy
class function ClientRouting: TRestClientRoutingClass; override;
The associated routing class on the client side
- this overriden method returns TRestClientRoutingRest
TAuthSessionParent = class(TSynPersistent)
Used for efficient TAuthSession.IDCardinal comparison
TAuthSession = class(TAuthSessionParent)
Class used to maintain in-memory sessions
- this is not a TOrm table so won't be remotely accessible, for performance and security reasons
- the User field is a true instance, copy of the corresponding database content (for better speed)
- you can inherit from this class, to add custom session process
constructor Create(aCtxt: TRestServerUriContext; aUser: TAuthUser); reintroduce; virtual;
Initialize a session instance with the supplied TAuthUser instance
- this aUser instance will be handled by the class until Destroy
- raise an exception on any error
- on success, will also retrieve the aUser.Data BLOB field content
constructor CreateFrom(var Read: TFastReader; Server: TRestServer; tix: Int64); virtual;
Initialize a session instance from some persisted buffer
- following the TRestServer.SessionsSaveToFile binary layout
destructor Destroy; override;
Will release the User and User.GroupRights instances
procedure NotifyInterfaces(aCtxt: TRestServerUriContext; aElapsed: Int64);
Update the Interfaces[] statistics
property AccessRights: TOrmAccessRights read fAccessRights;
Copy of the associated user access rights
- extracted from User.TAuthGroup.OrmAccessRights
property ConnectionID: TRestConnectionID read fConnectionID;
The low-level ConnectionID of the connection initiating this session
property GroupID: TID read GetGroupID;
The associated Group ID, as in User.GroupRights.ID
property ID: cardinal read fID;
The session ID number, as numerical value
- never equals to 1 (CONST_AUTHENTICATION_NOT_USED, i.e. authentication mode is not enabled), nor 0 (CONST_AUTHENTICATION_SESSION_NOT_STARTED, i.e. session still in handshaking phase)
property Interfaces: TSynMonitorInputOutputObjArray read fInterfaces write fInterfaces;
Per-session statistics about interface-based services
- Interfaces[] follows TRestServer.Services.fListInterfaceMethod[] array
- is initialized and maintained only if mlSessions is defined in TRestServer.StatLevels property
property Methods: TSynMonitorInputOutputObjArray read fMethods;
Per-session statistics about method-based services
- Methods[] follows TRestServer.fPublishedMethod[] array
- is initialized and maintained only if mlSessions is defined in TRestServer.StatLevels property
property PrivateKey: RawUtf8 read fPrivateKey;
The hexadecimal private key as returned to the connected client as 'SessionID+PrivateKey'
property RemoteIP: RawUtf8 read fRemoteIP;
The remote IP, if any
- is extracted from SentHeaders properties
property RemoteOS: RawUtf8 read GetRemoteOS;
The client Operating System, if sent from a mORMot 2 client
- is extracted from 'clientnonce' by TRestServerAuthenticationDefault.Auth into RemoteOsVersion 32-bit flags
- returns e.g. 'Windows 11 64-bit 22000' or 'Debian 5.4.0'
property RemoteOsVersion: TOperatingSystemVersion read fRemoteOsVersion;
The Client Operating System
- as extracted from 'clientnonce' by TRestServerAuthenticationDefault.Auth
property SentHeaders: RawUtf8 read fSentHeaders;
The transmitted HTTP headers, if any
- can contain e.g. 'RemoteIp: 127.0.0.1' or 'User-Agent: Mozilla/4.0'
property TimeoutShr10: cardinal read fTimeOutShr10;
The timestamp (in numbers of 1024 ms) until a session is kept alive
- extracted from User.TAuthGroup.SessionTimeout
- is used for fast comparison with GetTickCount64 shr 10
property TimeOutTix: cardinal read fTimeOutTix;
Set by the Access() method to the current GetTickCount64 shr 10 timestamp + TimeoutSecs
property User: TAuthUser read fUser;
The associated User
- this is a true TAuthUser instance, and User.GroupRights will contain also a true TAuthGroup instance
property UserID: TID read GetUserID;
The associated User ID, as in User.ID
property UserName: RawUtf8 read GetUserName;
The associated User Name, as in User.LogonName
TRestServerAuthentication = class(TSynLocked)
Abstract class used to implement server-side authentication in TRestServer
- inherit from this class to implement expected authentication scheme
- each TRestServerAuthentication class is associated with a TRestClientAuthentication class from mormot.rest.client.pas
constructor Create(aServer: TRestServer); reintroduce; virtual;
Initialize the authentication method to a specified server
- you can define several authentication schemes for the same server
function Auth(Ctxt: TRestServerUriContext): boolean; virtual; abstract;
Called by the Server to implement the Auth RESTful method
- overridden method shall return TRUE if the request has been handled
- returns FALSE to let the next registered TRestServerAuthentication class to try implementing the content
- Ctxt.Parameters has been tested to contain an UserName=... value
- method execution is protected by TRestServer.Sessions.WriteLock
function RetrieveSession( Ctxt: TRestServerUriContext): TAuthSession; virtual; abstract;
Called by the Server to check if the execution context match a session
- returns a session instance corresponding to the remote request, and fill Ctxt.Session* members according to in-memory session information
- returns nil if this remote request does not match this authentication
- method execution is protected by TRestServer.Sessions.Safe
property Options: TRestServerAuthenticationOptions read fOptions write fOptions;
Allow to tune the authentication process
- default value is [saoUserByLogonOrID]
TRestServerAuthenticationUri = class(TRestServerAuthentication)
Weak authentication scheme using URL-level parameter
function RetrieveSession( Ctxt: TRestServerUriContext): TAuthSession; override;
Will check URI-level signature
- retrieve the session ID from 'session_signature=...' parameter
- method execution is protected by TRestServer.Sessions.ReadOnlyLock
TRestServerAuthenticationSignedUri = class(TRestServerAuthenticationUri)
Secure authentication scheme using URL-level digital signature
- match TRestClientAuthenticationSignedUri on Client side
- for instance, default suaCRC32 format of session_signature is
Hexa8(SessionID)+ Hexa8(Timestamp)+ Hexa8(crc32('SessionID+HexaSessionPrivateKey'+Sha256('salt'+PassWord)+ Hexa8(Timestamp)+url))
constructor Create(aServer: TRestServer); override;
Initialize the authentication method to a specified server
function RetrieveSession( Ctxt: TRestServerUriContext): TAuthSession; override;
Will check URI-level signature
- check session_signature=... parameter to be a valid digital signature
- method execution is protected by TRestServer.Sessions.ReadOnlyLock
property Algorithm: TRestAuthenticationSignedUriAlgo write SetAlgorithm;
Customize the session_signature signing algorithm
- you need to set this value on the server side only; those known algorithms will be recognized by TRestClientUri on the client side during the session handshake, to select the matching ComputeSignature function
property ComputeSignature: TOnRestAuthenticationSignedUriComputeSignature read fComputeSignature write fComputeSignature;
Customize the session_signature signing algorithm with a specific function
- the very same function should be set on TRestClientUri
- to select a known hash algorithm, you may change the Algorithm property
property NoTimestampCoherencyCheck: boolean read fNoTimestampCoherencyCheck write SetNoTimestampCoherencyCheck;
Allow any order when creating sessions
- by default, signed sessions are expected to be sequential, and new signed session signature can't be older in time than the last one, with a tolerance of TimestampCoherencySeconds
- but if your client is asynchronous (e.g. for AJAX requests), session may be rejected due to the delay involved on the client side: you can set this property to TRUE to enabled a weaker but more tolerant behavior
(aServer.AuthenticationRegister(TRestServerAuthenticationDefault) as TRestServerAuthenticationSignedUri).NoTimestampCoherencyCheck := true;
property TimestampCoherencySeconds: cardinal read fTimestampCoherencySeconds write SetTimestampCoherencySeconds;
Time tolerance in seconds for the signature timestamps coherency check
- by default, signed sessions are expected to be sequential, and new signed session signature can't be older in time than the last one, with a tolerance time defined by this property
- default value is 5 seconds, which cover most kind of clients (AJAX or WebSockets), even over a slow Internet connection
TRestServerAuthenticationDefault = class(TRestServerAuthenticationSignedUri)
MORMot secure RESTful authentication scheme on Server
- match TRestClientAuthenticationDefault on Client side
- this method will use a password stored via safe SHA-256 hashing in the TAuthUser ORM table
function Auth(Ctxt: TRestServerUriContext): boolean; override;
Will try to handle the Auth RESTful method with mORMot authentication
- to be called in a two pass "challenging" algorithm:
GET ModelRoot/auth?UserName=...
-> returns an hexadecimal nonce contents (valid for 5 minutes)
GET ModelRoot/auth?UserName=...&PassWord=...&ClientNonce=...
-> if password is OK, will open the corresponding session
and return 'SessionID+HexaSessionPrivateKey'The Password parameter as sent for the 2nd request will be computed as
Sha256(ModelRoot+Nonce+ClientNonce+UserName+Sha256('salt'+PassWord))
- the returned HexaSessionPrivateKey content will identify the current user logged and its corresponding session (the same user may have several sessions opened at once, each with its own private key)
- then the private session key must be added to every query sent to the server as a session_signature=???? parameter, which will be computed as such:
ModelRoot/url?A=1&B=2&session_signature=012345670123456701234567
were the session_signature= parameter will be computed as such:
Hexa8(SessionID)+Hexa8(Timestamp)+ Hexa8(crc32('SessionID+HexaSessionPrivateKey'+Sha256('salt'+PassWord)+ Hexa8(Timestamp)+url)) with url='ModelRoot/url?A=1&B=2'
this query authentication uses crc32 for hashing instead of SHA-256 in in order to lower the Server-side CPU consumption; the salted password (i.e. TAuthUser.PasswordHashHexa) and client-side Timestamp are inserted inside the session_signature calculation to prevent naive man-in-the-middle attack (MITM)
- the session ID will be used to retrieve the rights associated with the user which opened the session via a successful call to the Auth service
- when you don't need the session any more (e.g. if the TRestClientUri instance is destroyed), you can call the service as such:
GET ModelRoot/auth?UserName=...&Session=...
- for a way of computing SHA-256 in JavaScript, see for instance @http://www.webtoolkit.info/javascript-sha256.html
TRestServerAuthenticationNone = class(TRestServerAuthenticationUri)
MORMot weak RESTful authentication scheme
- match TRestClientAuthenticationNone on Client side
- this method will authenticate with a given username, but no signature
- on client side, this scheme is not called by TRestClientUri.SetUser() method - so you have to write:
TRestServerAuthenticationNone.ClientSetUser(Client,'User','');
function Auth(Ctxt: TRestServerUriContext): boolean; override;
Will try to handle the Auth RESTful method with mORMot authentication
- to be called in a weak one pass request:
GET ModelRoot/auth?UserName=...
-> if the specified user name exists, will open the corresponding
session and return 'SessionID+HexaSessionPrivateKey'TRestServerAuthenticationHttpAbstract = class(TRestServerAuthentication)
Abstract class for implementing HTTP authentication
- do not use this abstract class, but e.g. TRestServerAuthenticationHttpBasic
- 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
function RetrieveSession(Ctxt: TRestServerUriContext): TAuthSession; override;
Will check the caller signature
- retrieve the session ID from "Cookie: mORMot_session_signature=..." HTTP header
- method execution is protected by TRestServer.Sessions.ReadOnlyLock
TRestServerAuthenticationHttpBasic = class(TRestServerAuthenticationHttpAbstract)
Authentication using HTTP Basic scheme
- match TRestClientAuthenticationHttpBasic on Client side
- this protocol send both name and password as clear (just Base64 encoded) so should only be used over TLS / HTTPS, or for compatibility reasons
- will rely on TRestServerAuthenticationNone for authorization
- on client side, this scheme is not called by TRestClientUri.SetUser() method - so you have to write:
TRestServerAuthenticationHttpBasic.ClientSetUser(Client,'User','password');
- for a remote proxy-only authentication (without creating any mORMot session), you can write:
TRestServerAuthenticationHttpBasic.ClientSetUserHttpOnly(Client,'proxyUser','proxyPass');
function Auth(Ctxt: TRestServerUriContext): boolean; override;
Handle the Auth RESTful method with HTTP Basic
- will first return HTTP_UNAUTHORIZED (401), then expect user and password to be supplied as incoming "Authorization: Basic ...." headers
function RetrieveSession(Ctxt: TRestServerUriContext): TAuthSession; override;
Will check URI-level signature
- retrieve the session ID from 'session_signature=...' parameter
- will also check incoming "Authorization: Basic ...." HTTP header
- method execution should be protected by TRestServer.fSessions.Lock
TRestServerAuthenticationSspi = class(TRestServerAuthenticationSignedUri)
Authentication of the current logged user using Windows Security Support Provider Interface (SSPI) or the 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
- 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
- this class is not available on some targets (e.g. Android)
constructor Create(aServer: TRestServer); override;
Initialize this SSPI/GSSAPI authentication scheme
destructor Destroy; override;
Finalize internal sspi/gssapi allocated structures
function Auth(Ctxt: TRestServerUriContext): boolean; override;
Will try to handle the RESTful authentication via SSPI/GSSAPI
- to be called in a two pass algorithm, used to cypher the password
- the client-side logged user will be identified as valid, according to a Windows SSPI API secure challenge
TRestServerMonitor = class(TSynMonitorServer)
Used for high-level statistics in TRestServer.Uri()
constructor Create(aServer: TRestServer); reintroduce;
Initialize the instance
destructor Destroy; override;
Finalize the instance
function NotifyThreadCount(delta: integer): integer;
Update and returns the CurrentThreadCount property
- this method is thread-safe
procedure NotifyOrm(aMethod: TUriMethod);
Update the Created/Read/Updated/Deleted properties
- this method is thread-safe
procedure NotifyOrmTable(TableIndex, DataSize: integer; Write: boolean; const MicroSecondsElapsed: QWord);
Update the per-table statistics
- this method is thread-safe
procedure ProcessSuccess(IsOutcomingFile: boolean);
Should be called when a task successfully ended
- thread-safe method
property Created: TSynMonitorCount64 read fCreated;
How many Create / Add ORM operations did take place
property CurrentThreadCount: TSynMonitorOneCount read fCurrentThreadCount;
Number of current declared threads count
- as registered by BeginCurrentThread/EndCurrentThread
property Deleted: TSynMonitorCount64 read fDeleted;
How many Delete ORM operations did take place
property OutcomingFiles: TSynMonitorCount64 read fOutcomingFiles;
Count of files transmitted directly (not part of Output size property)
- i.e. when the service uses STATICFILE_CONTENT_TYPE/HTTP_RESP_STATICFILE as content type to let the HTTP server directly serve the file content
property Read: TSynMonitorCount64 read fRead;
How many Read / Get ORM operations did take place
property ServiceInterface: TSynMonitorCount64 read fServiceInterface;
Count of the remote interface-based service calls
property ServiceMethod: TSynMonitorCount64 read fServiceMethod;
Count of the remote method-based service calls
property StartDate: RawUtf8 read fStartDate;
When this monitoring instance (therefore the server) was created
property Success: TSynMonitorCount64 read fSuccess;
Number of valid responses
- i.e. which returned status code 200/HTTP_SUCCESS or 201/HTTP_CREATED
- any invalid request will increase the TSynMonitor.Errors property
property Updated: TSynMonitorCount64 read fUpdated;
How many Update ORM operations did take place
TOrmMonitorUsage = class(TOrmNoCaseExtended)
ORM table used to store TSynMonitorUsage information in TSynMonitorUsageRest
- the ID primary field is the TSynMonitorUsageID (accessible from UsageID public property) shifted by 16-bit (by default) to include a TSynUniqueIdentifierProcess value
function UsageID(aProcessIDShift: integer = 16): integer;
Compute the corresponding 23 bit TSynMonitorUsageID.Value time slice
- according to the stored Process field, after bit shift
- allows a custom aProcessIDShift if it is not set as default 16-bit
property Comment: RawUtf8 read fComment write fComment;
A custom text, which may be used e.g. by support or developpers
property Gran: TSynMonitorUsageGranularity read fGran write fGran;
The granularity of the statistics of this entry
property Info: variant read fInfo write fInfo;
The actual statistics information, stored as a TDocVariant JSON object
property Process: Int64 read fProcess write fProcess;
Identify which application is monitored
- match the lower bits of each record ID
- by default, is expected to be a TSynUniqueIdentifierProcess 16-bit value
TSynMonitorUsageRest = class(TSynMonitorUsage)
Will store TSynMonitorUsage information in TOrmMonitorUsage ORM tables
- TOrm.ID will be the TSynMonitorUsageID shifted by ProcessIDShift bits
constructor Create(const aStorage: IRestOrm; aProcessID: Int64; aStoredClass: TOrmMonitorUsageClass = nil; aProcessIDShift: integer = 16); reintroduce; virtual;
Initialize storage via ORM
- if a 16-bit TSynUniqueIdentifierProcess is supplied, it will be used to identify the generating process by shifting TSynMonitorUsageID values by aProcessIDShift bits (default 16 but you may increase it up to 40 bits)
- will use TOrmMonitorUsage table, unless another one is specified
destructor Destroy; override;
Finalize the process, saving pending changes
property ProcessID: Int64 read fProcessID;
How the information could be stored for several processes
- e.g. when several SOA nodes gather monitoring information in a shared (MongoDB) database
- is by default a TSynUniqueIdentifierProcess value, but may be any integer up to ProcessIDShift bits as set in Create()
property ProcessIDShift: integer read fProcessIDShift;
How process ID are stored within the mORMot TOrm.ID
- equals 16-bit by default, to match TSynUniqueIdentifierProcess resolution
property SaveBatch: TRestBatch read fSaveBatch write fSaveBatch;
You can set an optional Batch instance to speed up DB writing
- when calling the Modified() method
property StoredClass: TOrmMonitorUsageClass read fStoredClass;
The actual ORM class used for persistence
TRestTreeNodeData = record
REST-specific context information, as stored in TRestTreeNode
Blob: TOrmPropInfoRttiRawBlob;
The ORM BLOB field definition for rnTableIDBlob
Command: TRestServerUriContextCommand;
The ORM/SOA TRestServer execution context
MethodIndex: SmallInt ;
The index of the associated method (16-bit is enough, -1 for none)
- for rn*Method*, in TRestServer.PublishedMethod[]
- for rnInterface*, in Service.InterfaceFactory.Methods[MethodIndex-4] or 0..3 for internal _free_/_contract_/_signature_/_instance_ pseudo-methods
Node: TRestNode;
Which kind of execution this node is about
Service: TServiceFactoryServerAbstract;
The interface-based service for rnInterface
Table: TOrmModelProperties;
The properties of the ORM class in the server TOrmModel for rnTable*
TableMain: TRestOrm;
The main engine of this Table ORM class - set at runtime
TableStatic: TRestOrm;
The static engine of this Table ORM class - set at runtime
TableStaticKind: TRestServerKind;
The static engine kind of this Table ORM class - set at runtime
TRestTreeNode = class(TRadixTreeNodeParams)
Implement a Radix Tree node to hold one URI registration
Data: TRestTreeNodeData;
REST-specific context information, as cloned by Split()
function Split(const Text: RawUtf8): TRadixTreeNode; override;
Overriden to support the additional Data fields
ERestTree = class(ERadixTree)
Exception class raised during TRestTree URI parsing
TRestRouter = class(TSynPersistent)
Efficient server-side URI routing for TRestServer
constructor Create(aOwner: TRestServer); reintroduce;
Initialize this URI routine engine
destructor Destroy; override;
Finalize this URI routing engine
function InfoText: RawUtf8;
Used by ComputeRoutes to log the current route registration state
function Lookup(Ctxt: TRestServerUriContext): TRestTreeNode;
Quickly search for the node corresponding to Ctxt.Method and Uri
- should never raise an exception
function Setup(aFrom: TUriMethod; const aUri: RawUtf8; aNode: TRestNode): TRestTreeNode; overload;
Register a given URI to the tree, for a given HTTP method
- 'modelroot/' will be prefixed to the supplied aUri
procedure Setup(aFrom: TUriMethods; const aUri: RawUtf8; aNode: TRestNode; aTable: TOrmModelProperties; aBlob: TOrmPropInfoRttiRawBlob = nil; aMethodIndex: integer = -1; aService: TServiceFactory = nil); overload;
Register a given URI to the tree, for a given HTTP method
- 'modelroot/' will be prefixed to the supplied aUri
property Tree: TRestRouterTree read fTree;
Access to the internal per-method TRestTree instance
- some Tree[] may be nil if the HTTP method has not been registered yet
TRestServerUriPagingParameters = record
Structure used to specify custom request paging parameters for TRestServer
- default values are the one used for YUI component paging (i.e. PAGINGPARAMETERS_YAHOO constant, as set by TRestServer.Create)
- warning: using paging can be VERY expensive on Server side, especially when used with external databases (since all data is retrieved before paging, when SQLite3 works in virtual mode)
Dir: RawUtf8;
Parameter name used to specify the request sort direction
- default value is 'DIR='
- note that any custom value should be uppercase and end with a '=' character
Results: RawUtf8;
Parameter name used to specify the request the page size (LIMIT clause)
- default value is 'RESULTS='
- note that any custom value should be uppercase and end with a '=' character
Select: RawUtf8;
Parameter name used to specify the request field names
- default value is 'SELECT='
- note that any custom value should be uppercase and end with a '=' character
SendTotalRowsCountFmt: RawUtf8;
Returned JSON field value of optional total rows count
- default value is '', i.e. no total rows count field
- computing total rows count can be very expensive, depending on the database back-end used (especially for external databases)
- can be set e.g. to ',"totalRows":%' value (note that the initial "," is expected by the produced JSON content, and % will be set with the value)
Sort: RawUtf8;
Parameter name used to specify the request sort order
- default value is 'SORT='
- note that any custom value should be uppercase and end with a '=' character
StartIndex: RawUtf8;
Parameter name used to specify the request starting offset
- default value is 'STARTINDEX='
- note that any custom value should be uppercase and end with a '=' character
Where: RawUtf8;
Parameter name used to specify the request WHERE clause
- default value is 'WHERE='
- note that any custom value should be uppercase and end with a '=' character
TRestServer = class(TRest)
Abstract REpresentational State Transfer (REST) server
- don't use this abstract class, but override and implement the protected EngineList() Retrieve() Add() Update() Delete() methods
- so if you want a REST server with no ORM (e.g. for a pure SOA server), use (or inherit) TRestServerFullMemory; if you want a REST server with tied ORM (with SQLite3 or any external DB), use TRestServerDB
- automatic call of this methods by a generic Uri() RESTful function
- any published method of descendants must match TOnRestServerCallBack prototype, and is expected to be thread-safe
OnAfterUri: TOnAfterUri;
Event trigerred when Uri() finished to process an ORM/SOA command
- the supplied Ctxt parameter will give access to the command which has been executed, e.g. via Ctxt.Call.OutStatus or Ctxt.MicroSecondsElapsed
- since this event will be executed by every TRestServer.Uri call, it should better not make any slow process (like accessing a remote DB)
OnAuthenticationFailed: TOnAuthenticationFailed;
This event handler will be executed when a session failed to initialize (DenyOfService attack?) or the request is not valid (ManIntheMiddle attack?)
- e.g. if the URI signature is invalid, or OnSessionCreate event handler aborted the session creation by returning TRUE (in this later case, the Session parameter is not nil)
- you can access the current execution context from the Ctxt parameter, e.g. to retrieve the caller's IP and ban aggressive users in Ctxt.RemoteIP or the text error message corresponding to Reason in Ctxt.CustomErrorMsg
OnAuthenticationUserRetrieve: TOnAuthenticationUserRetrieve;
A custom method to retrieve the TAuthUser instance for authentication
- will be called by TRestServerAuthentication.GetUser() instead of plain AuthUserClass.Create()
OnBeforeUri: TOnBeforeUri;
Event trigerred when Uri() is about to execute an ORM/SOA command
- the supplied Ctxt parameter will give access to the command about to be executed, e.g. Ctxt.Command=execSoaByInterface will identify a SOA service execution, with the corresponding Service and ServiceMethodIndex parameters as set by TRestServerUriContext.UriDecodeSoaByInterface
- should return TRUE if the method can be executed
- should return FALSE if the method should not be executed, and the callback should set the corresponding error to the supplied context e.g.
Ctxt.Error('Unauthorized method',HTTP_NOTALLOWED);- since this event will be executed by every TRestServer.Uri call, it should better not make any slow process (like accessing a remote DB)
OnErrorUri: TOnErrorUri;
Event trigerred when Uri() raise an exception and failed to process a request
- if Ctxt.ExecuteCommand raised an exception, this callback will be run with all neeed information
- should return TRUE to execute Ctxt.Error(E,...), FALSE if returned content has already been set as expected by the client
OnIdle: TNotifyEvent;
Event trigerred when Uri() is called, and at least 128 ms is elapsed
- could be used to execute some additional process after a period of time
- note that if TRestServer.Uri is not called by any client, this callback won't be executed either - consider using TRestServer.Run instead
OnInternalInfo: TOnInternalInfo;
Event to customize the information returned by root/timestamp/info
- called by TRestServer.InternalInfo method
- you can add some application-level information for monitoring
OnServiceCreateInstance: TOnServiceCreateInstance;
This event will be executed by TServiceFactoryServer.CreateInstance
- you may set a callback to customize a server-side service instance, i.e. inject class-level dependencies:
procedure TMyClass.OnCreateInstance( Sender: TServiceFactoryServer; Instance: TInterfacedObject); begin if Sender.ImplementationClass=TLegacyStockQuery then TLegacyStockQuery(Instance).fDbConnection := fDbConnection; end;
- consider using a TInjectableObjectClass implementation for pure IoC/DI
OnSessionClosed: TOnOrmSession;
A method can be specified to be notified when a session is closed
- for OnSessionClosed, the returning boolean value is ignored
- Ctxt is nil if the session is closed due to a timeout
- Ctxt is not nil if the session is closed explicitly by the client
OnSessionCreate: TOnOrmSession;
A method can be specified to be notified when a session is created
- for OnSessionCreate, returning TRUE will abort the session creation - and you can set Ctxt.Call^.OutStatus to a corresponding error code
- it could be used e.g. to limit the number of client sessions
OnStartUri: TOnStartUri;
Event trigerred when Uri start to process a request
- should return HTTP_SUCCESS (200) to continue, or an error code to abort
- could also change the Call fields on the fly, if needed
UriPagingParameters: TRestServerUriPagingParameters;
This property can be used to specify the URI parmeters to be used for paged queries
- is set by default to PAGINGPARAMETERS_YAHOO constant by TRestServer.Create() constructor
constructor Create(const aRoot: RawUtf8); reintroduce; overload;
Server initialization with a void Database Model and not authentication
- could be used e.g. for a interface-based services API REST server
constructor Create(aModel: TOrmModel; aHandleUserAuthentication: boolean = false); reintroduce; overload; virtual;
Server initialization with a specified Database Model
- if HandleUserAuthentication is false, will set URI access rights to 'Supervisor' (i.e. all R/W access) by default
- if HandleUserAuthentication is true, will add TAuthUser and TAuthGroup to the TOrmModel (if not already there)
constructor CreateWithOwnModel(const Tables: array of TOrmClass; aHandleUserAuthentication: boolean = false; const aRoot: RawUtf8 = 'root');
Server initialization with a temporary Database Model
- a Model will be created with supplied tables, and owned by the server
- if you instantiate a TRestServerFullMemory or TRestServerDB with this constructor, an in-memory engine will be created, with enough abilities to run regression tests, for instance
constructor RegisteredClassCreateFrom(aModel: TOrmModel; aDefinition: TSynConnectionDefinition; aServerHandleAuthentication: boolean); override;
Initialize REST server instance from a TSynConnectionDefinition
destructor Destroy; override;
Server finalization
function AuthenticationRegister( aMethod: TRestServerAuthenticationClass): TRestServerAuthentication; overload;
Call this method to add an authentication method to the server
- will return the just created TRestServerAuthentication instance, or the existing instance if it has already been registered
- you can use this method to tune the authentication, e.g. if you have troubles with AJAX asynchronous callbacks:
(aServer.AuthenticationRegister(TRestServerAuthenticationDefault) as TRestServerAuthenticationDefault).NoTimestampCoherencyCheck := true;
or if you want to customize the session_signature parameter algorithm:
(aServer.AuthenticationRegister(TRestServerAuthenticationDefault) as TRestServerAuthenticationDefault).Algorithm := suaMD5;
function BanIP(const aIP: RawUtf8; aRemoveBan: boolean = false): boolean;
(un)register a banned IPv4 value
- any connection attempt from this IP Address will be rejected by
function ExportServerGlobalLibraryRequest(Disable: boolean = false): boolean;
Grant access to this database content from a dll using the global LibraryRequest() function
- returns true if the LibraryRequest() function is implemented by this TRestServer, and TRestClientLibraryRequest can access it
- returns false if a TRestServer was already exported
- call with Disable=true to remove the LibraryRequest() function binding
function GetCurrentSessionUserID: TID; override;
Retrieve the current session TAuthUser.ID (if any) from the ServiceRunningContext threadvar
function GetRecordVersionMax(TableIndex: integer): TRecordVersion;
Read access to the TRestOrmServer.RecordVersionMax[TableIndex] property
- used internally by TServiceContainerServer for client/server synchronization
function JwtForUnauthenticatedRequestWhiteIP(const aIP: RawUtf8; aRemoveWhite: boolean = false): boolean;
(un)register a an IPv4 value to the JWT white list
- by default, a JWT validated by JwtForUnauthenticatedRequest will be accepted
- to avoid MiM (Man-In-the-Middle) attacks, if a JWT white list is defined using this method, any connection from a non registered IP will be rejected, even with a valid JWT
- WebSockets connections are secure enough to bypass this list
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
- is a TRestOrmServer instance
function RecordVersionSynchronizeMasterStart( ByPassAuthentication: boolean = false): boolean;
Initiate asynchronous master/slave replication on a master TRest
- allow synchronization of a TOrm table, using its TRecordVersion field, for real-time master/slave replication on the master side
- this method will register the IServiceRecordVersion service on the server side, so that RecordVersionSynchronizeStartSlave() will be able to receive push notifications of any updates
- this method expects the communication channel to be bidirectional, e.g. a mormot.rest.http.server's TRestHttpServer in HTTP_BIDIR mode (either useBidirSocket or useBidirAsync - see WEBSOCKETS_DEFAULT_MODE)
function RecordVersionSynchronizeSlaveStart(Table: TOrmClass; MasterRemoteAccess: TRestClientUri; const OnNotify: TOnBatchWrite = nil): boolean;
Initiate asynchronous master/slave replication on a slave TRest
- start synchronization of a TOrm table, using its TRecordVersion field, for real-time master/slave replication on the slave side
- this method will first retrieve any pending modification by regular REST calls to RecordVersionSynchronizeSlave, then create and register a callback instance using RecordVersionSynchronizeSubscribeMaster()
- this method expects the communication channel to be bidirectional, e.g. a TRestHttpClientWebsockets
- the modifications will be pushed by the master, then applied to the slave storage, until RecordVersionSynchronizeSlaveStop method is called
- an optional OnNotify event may be defined, which will be triggered for all incoming change, supllying the updated TOrm instance
function RecordVersionSynchronizeSlaveStop(Table: TOrmClass): boolean;
Finalize asynchronous master/slave replication on a slave TRest
- stop synchronization of a TOrm table, using its TRecordVersion field, for real-time master/slave replication on the slave side
- expect a previous call to RecordVersionSynchronizeSlaveStart
function RecordVersionSynchronizeSubscribeMaster(Table: TOrmClass; RecordVersion: TRecordVersion; const SlaveCallback: IServiceRecordVersionCallback): boolean; overload;
Low-level callback registration for asynchronous master/slave replication
- you should not have to use this method, but rather RecordVersionSynchronizeMasterStart and RecordVersionSynchronizeSlaveStart RecordVersionSynchronizeSlaveStop methods
- register a callback interface on the master side, which will be called each time a write operation is performed on a given TOrm with a TRecordVersion field
- the callback parameter could be a TServiceRecordVersionCallback instance, which will perform all update operations as expected
- the callback process will be blocking for the ORM write point of view: so it should be as fast as possible, or asynchronous - note that regular callbacks using WebSockets, as implemented by mormot.net.ws.core.server and mormot.rest.http.server's TRestHttpServer in HTTP_BIDIR mode (either useBidirSocket or useBidirAsync - see WEBSOCKETS_DEFAULT_MODE) useBidirSocket/useBidirAsync mode
- if the supplied RecordVersion is not the latest on the server side, this method will return FALSE and the caller should synchronize again via RecordVersionSynchronize() to avoid any missing update
- if the supplied RecordVersion is the latest on the server side, this method will return TRUE and put the Callback notification in place
function ServiceContainer: TServiceContainer; override;
Access or initialize the internal IoC resolver
- overriden to create and initialize the internal TServiceContainerServer if no service interface has been registered yet
function ServiceDefine(aSharedImplementation: TInterfacedObject; const aInterfaces: array of TGuid; const aContractExpected: RawUtf8 = ''): TServiceFactoryServerAbstract; overload;
Register a Service instance on the server side
- this method expects the interface(s) to have been registered previously:
TInterfaceFactory.RegisterInterfaces([TypeInfo(IMyInterface),...]);
- the supplied aSharedImplementation will be owned by this Server instance
- will return the first of the registered TServiceFactoryServerAbstract on success (i.e. corresponding to aInterfaces[0] - not to the others), or nil if registration failed (e.g. if any of the supplied interfaces is not implemented by the given class)
function ServiceDefine(aClient: TRest; const aInterfaces: array of TGuid; aInstanceCreation: TServiceInstanceImplementation = sicSingle; const aContractExpected: RawUtf8 = ''): boolean; overload;
Register a remote Service via its interface
- this method expects the interface(s) to have been registered previously:
TInterfaceFactory.RegisterInterfaces([TypeInfo(IMyInterface),...]);
function ServiceDefine(aImplementationClass: TInterfacedClass; const aInterfaces: array of TGuid; aInstanceCreation: TServiceInstanceImplementation = sicSingle; const aContractExpected: RawUtf8 = ''): TServiceFactoryServerAbstract; overload;
Register a Service class on the server side
- this method expects the interface(s) to have been registered previously:
TInterfaceFactory.RegisterInterfaces([TypeInfo(IMyInterface),...]);
- will return the first of the registered TServiceFactoryServerAbstract on success (i.e. corresponding to aInterfaces[0] - not to the others), or nil if registration failed (e.g. if any of the supplied interfaces is not implemented by the given class)
function ServiceMethodByPassAuthentication( const aMethodName: RawUtf8): integer;
Call this method to disable Authentication method check for a given published method-based service name
- by default, only Auth and Timestamp methods do not require the RESTful authentication of the URI; you may call this method to add another method to the list (e.g. for returning some HTML content from a public URI)
- if the supplied aMethodName='', all method-based services will bypass the authenticaton process
- returns the method index number
function ServiceMethodRegister(aMethodName: RawUtf8; const aEvent: TOnRestServerCallBack; aByPassAuthentication: boolean = false; aMethods: TUriMethods = [mGET, mPOST, mPUT, mDELETE]): PtrInt;
Direct registration of a method for a given low-level event handler
- returns the index in the fPublishedMethod[] internal array
- will use the supplied aMethods or detect '_VERB1_[_VERB2_][..]MethodName' pattern e.g. as '_GET_Info' or '_GET__DELETE_User'
function ServiceRegister(aSharedImplementation: TInterfacedObject; const aInterfaces: array of PRttiInfo; const aContractExpected: RawUtf8 = ''): TServiceFactoryServerAbstract; overload; virtual;
Register a Service instance on the server side
- this methods expects a class instance to be supplied, and the exact list of interfaces to be registered to the server (e.g. [TypeInfo(IMyInterface)]) and implemented by this shared instance
- as a consequence, instance implementation pattern will always be sicShared
- will return the first of the registered TServiceFactoryServer created on success (i.e. the one corresponding to the first item of the aInterfaces array), or nil if registration failed (e.g. if any of the supplied interfaces is not implemented by the given class)
- the same implementation class can be used to handle several interfaces (just as Delphi allows to do natively)
- will return the first of the registered TServiceFactoryServerAbstract on success (i.e. corresponding to aInterfaces[0] - not to the others), or nil if registration failed (e.g. if any of the supplied interfaces is not implemented by the given class)
function ServiceRegister(aImplementationClass: TInterfacedClass; const aInterfaces: array of PRttiInfo; aInstanceCreation: TServiceInstanceImplementation = sicSingle; const aContractExpected: RawUtf8 = ''): TServiceFactoryServerAbstract; overload; virtual;
Register a Service class on the server side
- this methods expects a class to be supplied, and the exact list of interfaces to be registered to the server (e.g. [TypeInfo(IMyInterface)]) and implemented by this class
- class can be any TInterfacedObject, but TInterfacedObjectWithCustomCreate can be used if you need an overridden constructor
- instance implementation pattern will be set by the appropriate parameter
- will return the first of the registered TServiceFactoryServer created on success (i.e. the one corresponding to the first item of the aInterfaces array), or nil if registration failed (e.g. if any of the supplied interfaces is not implemented by the given class)
- the same implementation class can be used to handle several interfaces (just as Delphi allows to do natively)
- will return the first of the registered TServiceFactoryServerAbstract on success (i.e. corresponding to aInterfaces[0] - not to the others), or nil if registration failed (e.g. if any of the supplied interfaces is not implemented by the given class)
function ServiceRegister(aClient: TRest; const aInterfaces: array of PRttiInfo; aInstanceCreation: TServiceInstanceImplementation = sicSingle; const aContractExpected: RawUtf8 = ''): boolean; overload; virtual;
Register a remote Service via its interface
- this overloaded method will register a remote Service, accessed via the supplied TRest/TRestClientUri instance: it can be available in the main TRestServer.Services property, but execution will take place on a remote server - may be used e.g. for dedicated hosting of services (in a DMZ for instance)
- 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 ServicesPublishedInterfaces: RawUtf8;
Compute a JSON description of all available services, and its public URI
- the JSON object matches the TServicesPublishedInterfaces record type
- used by TRestClientUri.ServicePublishOwnInterfaces to register all the services supported by the client itself
- warning: the public URI should have been set via SetPublicUri()
function SessionGetUser(aSessionID: cardinal): TAuthUser;
Returns a copy of the user associated to a session ID
- returns nil if the session does not exist (e.g. if authentication disabled)
- caller MUST release the TAuthUser instance returned (if not nil)
- this method IS thread-safe, calling internally Sessions.Safe.ReadOnlyLock (the returned TAuthUser is a private copy from Sessions[].User instance, in order to be really thread-safe)
- the returned TAuthUser instance will have GroupRights=nil but will have ID, LogonName, DisplayName, PasswordHashHexa and Data fields available
function SessionsAsJson: RawJson;
Retrieve all current session information as a JSON array
function SleepOrShutdown(MS: integer): boolean;
Wait for the specified number of milliseconds
- if Shutdown is called in-between, returns true
- if the thread waited the supplied time, returns false
procedure Auth(Ctxt: TRestServerUriContext);
REST service accessible from ModelRoot/Auth URI
- called by the clients for authentication and session management
- this method won't require an authenticated client, since it is used to initiate authentication
- this global callback method is thread-safe
procedure AuthenticationRegister( const aMethods: array of TRestServerAuthenticationClass); overload;
Call this method to add several authentication methods to the server
- if TRestServer.Create() constructor is called with aHandleUserAuthentication set to TRUE, it will register the two following classes:
AuthenticationRegister([ TRestServerAuthenticationDefault, TRestServerAuthenticationSspi]);
procedure AuthenticationUnregister( aMethod: TRestServerAuthenticationClass); overload;
Call this method to remove an authentication method to the server
procedure AuthenticationUnregister( const aMethods: array of TRestServerAuthenticationClass); overload;
Call this method to remove several authentication methods to the server
procedure AuthenticationUnregisterAll;
Call this method to remove all authentication methods to the server
procedure Batch(Ctxt: TRestServerUriContext);
REST service accessible from the ModelRoot/Batch URI
- will execute a set of RESTful commands, in a single step, with optional automatic SQL transaction generation
- this method will require an authenticated client, for safety
- expect input as JSON commands:
'{"Table":["cmd":values,...]}'or for multiple tables:
'["cmd@Table":values,...]'
with cmd in POST/PUT with {object} as value or DELETE with ID
- returns an array of integers: '[200,200,...]' or '["OK"]' if all returned status codes are 200 (HTTP_SUCCESS)
- URI are either 'ModelRoot/TableName/Batch' or 'ModelRoot/Batch'
procedure CacheFlush(Ctxt: TRestServerUriContext);
REST service accessible from the ModelRoot/CacheFlush URI
- it will flush the server result cache
- this method shall be called by the clients when the Server cache may be not consistent any more (e.g. after a direct write to an external database)
- this method will require an authenticated client, for safety
- GET ModelRoot/CacheFlush URI will flush the whole Server cache, for all tables
- GET ModelRoot/CacheFlush/TableName URI will flush the specified table cache
- GET ModelRoot/CacheFlush/TableName/TableID URI will flush the content of the specified record
- POST ModelRoot/CacheFlush/_callback_ URI will be called by the client to notify the server that an interface callback instance has been released
- POST ModelRoot/CacheFlush/_ping_ URI will be called by the client after every half session timeout (or at least every hour) to notify the server that the connection is still alive
procedure ComputeRoutes;
Can be called at startup to validate the URI routes on this server
- is also called from Uri() if needed (e.g. after ResetRoutes)
procedure CreateMissingTables(user_version: cardinal = 0; options: TOrmInitializeTableOptions = []);
Redirect to Server: IRestOrmServer methods
procedure RecordVersionHandle(Occasion: TOrmOccasion; TableIndex: integer; var Decoder: TJsonObjectDecoder; RecordVersionField: TOrmPropInfoRttiRecordVersion); virtual;
Low-level propagation of a record content
- used internally by TServiceContainerServer for client/server synchronization
procedure ResetRoutes;
Called when the routes need to be re-computed
- e.g. is called when a service has been registered, or options changes
procedure ServiceMethodRegisterPublishedMethods(const aPrefix: RawUtf8; aInstance: TObject; aMethods: TUriMethods = [mGET, mPOST, mPUT, mDELETE]);
Add all published methods of a given object instance to the method-based list of services
- all those published method signature should match TOnRestServerCallBack
- will use the supplied aMethods or detect '_VERB1_[_VERB2_][..]MethodName' pattern e.g. as '_GET_Info' or '_GET__DELETE_User'
procedure SessionsLoadFromFile(const aFileName: TFileName; andDeleteExistingFileAfterRead: boolean);
Re-create all in-memory sessions from a compressed binary file
- typical use is after a server restart, with the file supplied to the Shutdown() method: it could be used e.g. for a short maintenance server shutdown, without loosing the current logged user sessions
- WARNING: this method will restore authentication sessions for the ORM, but not any complex state information used by interface-based services, like sicClientDriven class instances - DO NOT use this feature with SOA
- this method IS thread-safe, and calls internally Sessions.Safe.WriteLock
procedure SessionsSaveToFile(const aFileName: TFileName);
Persist all in-memory sessions into a compressed binary file
- you should not call this method it directly, but rather use Shutdown() with a StateFileName parameter - to be used e.g. for a short maintenance server shutdown, without loosing the current logged user sessions
- this method IS thread-safe, and calls internally Sessions.Safe.ReadOnlyLock
procedure SetOrmInstance(aORM: TRestOrmParent); override;
Called by TRestOrm.Create overriden constructor to set fOrm from IRestOrm
procedure SetPublicUri(const Address, Port: RawUtf8);
The HTTP server should call this method so that ServicesPublishedInterfaces registration will be able to work
procedure SetRecordVersionMax(TableIndex: integer; Value: TRecordVersion);
Write access to the TRestOrmServer.RecordVersionMax[TableIndex] property
- used internally by TServiceContainerServer for client/server synchronization
procedure Shutdown(const aStateFileName: TFileName = ''); virtual;
You can call this method to prepare the server for shutting down
- it will reject any incoming request from now on, and will wait until all pending requests are finished, for proper server termination
- you could optionally save the current server state (e.g. user sessions) into a file, ready to be retrieved later on using SessionsLoadFromFile - note that this will work only for ORM sessions, NOT complex SOA state
- this method is called by Destroy itself
procedure Stat(Ctxt: TRestServerUriContext);
REST service accessible from ModelRoot/Stat URI to gather detailed information
- returns the current execution statistics of this server, as a JSON object
- this method will require an authenticated client, for safety
- by default, will return the high-level information of this server
- will return human-readable JSON layout if ModelRoot/Stat/json is used, or the corresponding XML content if ModelRoot/Stat/xml is used
- you can define withtables, withmethods, withinterfaces, withsessions or withsqlite3 additional parameters to return detailed information about method-based services, interface-based services, per session statistics, or prepared SQLite3 SQL statement timing (for a TRestServerDB instance)
Client.CallBackGet('stat',['withtables',true,'withmethods',true,
'withinterfaces',true,'withsessions',true,'withsqlite3',true],stats);- defining a 'withall' parameter will retrieve all available statistics
- note that TRestServer.StatLevels property will enable statistics gathering for tables, methods, interfaces, sqlite3 or sessions
- a specific findservice=ServiceName parameter will not return any statistics, but matching URIs from the server AssociatedServices list
procedure Timestamp(Ctxt: TRestServerUriContext);
REST service accessible from the ModelRoot/Timestamp URI
- returns the server time stamp TTimeLog/Int64 value as UTF-8 text
- this method will not require an authenticated client
- hidden ModelRoot/Timestamp/info command will return basic execution information, less verbose (and sensitive) than Stat(), calling virtual InternalInfo() protected method
procedure Uri(var Call: TRestUriParams); virtual;
Implement a generic local, piped or HTTP/1.1 provider
- this is the main entry point of the server, from the client side
- default implementation calls protected methods EngineList() Retrieve() Add() Update() Delete() UnLock() EngineExecute() above, which must be overridden by the TRestServer child
- for 'GET ModelRoot/TableName', url parameters can be either "select" and "where" (to specify a SQL Query, from the SqlFromSelectWhere function), either "sort", "dir", "startIndex", "results", as expected by the YUI DataSource Request Syntax for data pagination - see http://developer.yahoo.com/yui/datatable/#data
- execution of this method could be monitored via OnBeforeUri and OnAfterUri event handlers
property AssociatedServices: TServicesPublishedInterfacesList read fAssociatedServices;
A list of the services associated by all clients of this server instance
- when a client connects to this server, it will publish its own services (when checking its interface contract), so that they may be identified
property AuthenticationSchemes: TRestServerAuthenticationDynArray read fSessionAuthentication;
Read-only access to the list of registered server-side authentication methods, used for session creation
- note that the exact number or registered services in this list is stored in the AuthenticationSchemesCount property
property AuthenticationSchemesCount: integer read GetAuthenticationSchemesCount;
How many authentication methods are registered in AuthenticationSchemes
property AuthGroupClass: TAuthGroupClass read fAuthGroupClass;
The class inheriting from TAuthGroup, as defined in the model
- during authentication, this class will be used for every TAuthGroup table access
property AuthUserClass: TAuthUserClass read fAuthUserClass;
The class inheriting from TAuthUser, as defined in the model
- during authentication, this class will be used for every TAuthUser table access
- see also the OnAuthenticationUserRetrieve optional event handler
property BypassOrmAuthentication: TUriMethods read fBypassOrmAuthentication write fBypassOrmAuthentication;
Allow to by-pass Authentication for a given set of HTTP verbs
- by default, RESTful access to the ORM will follow HandleAuthentication setting: but you could define some HTTP verb to this property, which will by-pass the authentication - may be used e.g. for public GET of the content by an AJAX client
property HandleAuthentication: boolean read fHandleAuthentication;
Set to true if the server will handle per-user authentication and access right management
- i.e. if the associated TOrmModel contains TAuthUser and TAuthGroup tables (set by constructor)
property JwtForUnauthenticatedRequest: TJwtAbstract read fJwtForUnauthenticatedRequest write fJwtForUnauthenticatedRequest;
Define if unsecure connections (i.e. not in-process or encrypted WebSockets) with no session can be authenticated via JWT
- once set, this instance will be owned by the TRestServer
- by definition, such JWT authentication won't identify any mORMot user nor session (it just has to be valid), so only sicSingle, sicShared or sicPerThread interface-based services execution are possible
- typical usage is for a public API, in conjunction with ServiceDefine(...).ResultAsJsonObjectWithoutResult := true on the server side and TRestClientUri.ServiceDefineSharedApi() method for the client
- see also JwtForUnauthenticatedRequestWhiteIP() for additional security
property NoAjaxJson: boolean read GetNoAjaxJson write SetNoAjaxJson;
Set this property to true to transmit the JSON data in a "not expanded" format
- not directly compatible with Javascript object list decode: not to be used in AJAX environnement (like in TSqlite3HttpServer)
- but transmitted JSON data is much smaller if set it's set to FALSE, and if you use a Delphi Client, parsing will be also faster and memory usage will be lower
- By default, the NoAjaxJson property is set to TRUE in TRestServer.ExportServerNamedPipe: if you use named pipes for communication, you probably won't use javascript because browser communicates via HTTP!
- But otherwise, NoAjaxJson property is set to FALSE. You could force its value to TRUE and you'd save some bandwidth if you don't use javascript: even the parsing of the JSON Content will be faster with Delphi client if JSON content is not expanded
- the "expanded" or standard/AJAX layout allows you to create pure JavaScript objects from the JSON content, because the field name / JavaScript object property name is supplied for every value
- the "not expanded" layout, NoAjaxJson property is set to TRUE, reflects exactly the layout of the SQL request - first line contains the field names, then all next lines are the field content
- is in fact stored in rsoNoAjaxJson item in Options property
property OnNotifyCallback: TOnRestServerClientCallback read fOnNotifyCallback write SetOnNotifyCallback;
This event will be executed to push notifications from the WebSockets server to a remote client, using a (fake) interface parameter
- is nil by default, but may point e.g. to TRestHttpServer.NotifyCallback
- only a single WS server can be assigned to a TRestServer instance
property Options: TRestServerOptions read fOptions write SetOptions;
Allow to customize how TRestServer.Uri process the requests
- e.g. if HTTP_SUCCESS with no body should be translated into HTTP_NOCONTENT
property RootRedirectGet: RawUtf8 read fRootRedirectGet write fRootRedirectGet;
The URI to redirect any plain GET on root URI, without any method
- could be used to ease access from web browsers URI
- consider using faster and more precise THttpServerGeneric.Route.Get()
property Router: TRestRouter read fRouter;
Low-level access to the internal URI multiplexer
- to be used e.g. from overriden TRestServerUriContext.UriComputeRoutes
property Server: IRestOrmServer read fServer;
Main access to the IRestOrmServer methods of this instance
property ServiceMethodStat[const aMethod: RawUtf8]: TSynMonitorInputOutput read GetServiceMethodStat;
Retrieve detailed statistics about a method-based service use
- will return a reference to the actual alive item: caller should not free the returned instance
property ServiceReleaseTimeoutMicrosec: integer read fServiceReleaseTimeoutMicrosec write fServiceReleaseTimeoutMicrosec;
Maximum time allowed to release an interface service instance
- equals 500 microseconds by default - 0 would disable any measurement
- should be enabled for each given interface by setting optFreeTimeout
property ServicesRouting: TRestServerUriContextClass read fServicesRouting write SetRoutingClass;
The routing classs of the service remote request
- by default, will use TRestRoutingRest, i.e. an URI-based layout which is secure (since will use our RESTful authentication scheme), and also very fast
- but TRestRoutingJsonRpc can e.g. be set (on BOTH client and server sides), if the client will rather use JSON/RPC alternative pattern
- NEVER set the abstract TRestServerUriContext class on this property
property SessionClass: TAuthSessionClass read fSessionClass write fSessionClass;
The class inheriting from TAuthSession to handle in-memory sessions
- since all sessions data remain in memory, ensure they are not taking too much resource (memory or process time)
property Sessions: TSynObjectListSorted read fSessions;
Read-only access to the internal list of sessions
- ensure you protect its access using Sessions.Safe TRWLock
property ShutdownRequested: boolean read fShutdownRequested;
Flag set to TRUE when the Shutdown method has been called
property StatLevels: TRestServerMonitorLevels read fStatLevels write fStatLevels;
Which level of detailed information is gathered
- by default, contains SERVERDEFAULTMONITORLEVELS, i.e.
[mlUri, mlTables, mlMethods, mlInterfaces, mlSQLite3]
- you can add mlSessions to maintain per-session statistics: but it will slow down the process, with higher memory consumption for each session
property Stats: TRestServerMonitor read fStats;
Read-only access to the high-level Server statistics
- see ServiceMethodStat[] for information about method-based services, or TServiceFactoryServer.Stats / Stat[] for interface-based services
- statistics are available remotely as JSON from the Stat() method
property StatUsage: TSynMonitorUsage read fStatUsage write SetStatUsage;
Could be set to track statistic from Stats information
- it may be e.g. a TSynMonitorUsageRest instance for REST storage
- warning: current Uri() implementation is inefficient (single lock)
TRestHttpServerDefinition = class(TSynPersistentWithPassword)
Parameters supplied to publish a TRestServer via HTTP
- used by the overloaded TRestHttpServer.Create(TRestHttpServerDefinition) constructor in mormot.rest.http.server.pas, and also in dddInfraSettings.pas
constructor Create; override;
Initialize with the default values
property Authentication: TRestHttpServerRestAuthentication read fAuthentication write fAuthentication;
Which authentication is expected to be published
property BindPort: RawByteString read fBindPort write fBindPort;
Defines the port to be used for REST publishing
- may include an optional IP address to bind, e.g. '127.0.0.1:8888'
property DomainHostRedirect: RawUtf8 read fDomainHostRedirect write fDomainHostRedirect;
Register domain names to be redirected to a some Model.Root
- specified as CSV values of Host=Name pairs, e.g.
'project1.com=root1,project2.com=root2,blog.project2.com=root2/blog'
property EnableCors: RawUtf8 read fEnableCors write fEnableCors;
Allow Cross-origin resource sharing (CORS) access
- set this property to '*' if you want to be able to access the REST methods from an HTML5 application hosted in another location, or define a CSV white list of TMatch-compatible origins
- will set e.g. the following HTTP header:
Access-Control-Allow-Origin: *
property Https: boolean read fHttps write fHttps;
Defines if https:// protocol should be used
- implemented only by http.sys server under Windows, not by socket servers
property HttpSysQueueName: SynUnicode read fHttpSysQueueName write fHttpSysQueueName;
The displayed name in the http.sys queue
- used only by http.sys server under Windows, not by socket-based servers
property NginxSendFileFrom: TFileName read fNginxSendFileFrom write fNginxSendFileFrom;
Enable NGINX X-Accel internal redirection for STATICFILE_CONTENT_TYPE
- supplied value is passed as argument to THttpServer.NginxSendFileFrom()
- used only by the socket-based servers, not http.sys server on Windows
property Options: TRestHttpServerOptions read fOptions write fOptions;
Customize the TRestHttpServer low-level process
property RemoteIPHeader: RawUtf8 read fRemoteIPHeader write fRemoteIPHeader;
The value of a custom HTTP header containing the real client IP
- by default, the RemoteIP information will be retrieved from the socket layer - but if the server runs behind some proxy service, you should define here the HTTP header name which indicates the true remote client IP value, mostly as 'X-Real-IP' or 'X-Forwarded-For'
property RootRedirectToUri: RawUtf8 read fRootRedirectToUri write fRootRedirectToUri;
Redirect a '/' HTTP or HTTPS request to a given URI via a 307 command
- follow the Https property for the redirection source
property ThreadCount: byte read fThreadCount write fThreadCount;
How many threads the thread pool associated with this HTTP server should create
- if set to 0, will use default value 32
- this parameter may be ignored depending on the actual HTTP server used, which may not have any thread pool
property WebSocketPassword: SpiUtf8 read fPassWord write fPassWord;
If defined, this HTTP server will use WebSockets, and our secure encrypted binary protocol
- when stored in the settings JSON file, the password will be safely encrypted as defined by TSynPersistentWithPassword
- use the inherited PlainPassword property to set or read its value
PRestServerMethod = ^TRestServerMethod;
Pointer to a description of a method-based service
PServiceRunningContext = ^TServiceRunningContext;
Points to the currently running service on the server side
- your code may call the ServiceRunningContext global function once in a method, since per-thread access does cost some CPU
var context: PServiceRunningContext; begin context := ServiceRunningContext; // threadvar access once ...
TAuthSessionClass = class of TAuthSession;
Class-reference type (metaclass) used to define overridden session instances
- since all sessions data remain in memory, ensure they are not taking too much resource (memory or process time)
- if you plan to use session persistence, ensure you override the TAuthSession.SaveTo/CreateFrom methods in the inherited class
TOnAfterUri = procedure(Ctxt: TRestServerUriContext) of object;
Callback raised after TRestServer.Uri ORM/SOA command execution
TOnAuthenticationFailed = procedure(Sender: TRestServer; Reason: TOnAuthenticationFailedReason; Session: TAuthSession; Ctxt: TRestServerUriContext) of object;
Callback raised in case of authentication failure
- as used by TRestServerUriContext.AuthenticationFailed event
TOnAuthenticationFailedReason = ( afInvalidSignature, afRemoteServiceExecutionNotAllowed, afUnknownUser, afInvalidPassword, afSessionAlreadyStartedForThisUser, afSessionCreationAborted, afSecureConnectionRequired, afJWTRequired );
Used to identify the authentication failure reason
- as transmitted e.g. by TRestServerUriContext.AuthenticationFailed or TRestServer.OnAuthenticationFailed
TOnAuthenticationUserRetrieve = function(Sender: TRestServerAuthentication; Ctxt: TRestServerUriContext; aUserID: TID; const aUserName: RawUtf8): TAuthUser of object;
Callback allowing to customize the retrieval of an authenticated user
- as defined in TRestServer.OnAuthenticationUserRetrieve
- and executed by TRestServerAuthentication.GetUser
- on call, either aUserID will be <> 0, or aUserName is to be used
- if the function returns nil, default Server.AuthUserClass.Create() methods won't be called, and the user will be reported as not found
TOnBeforeUri = function(Ctxt: TRestServerUriContext): boolean of object;
Callback raised before TRestServer.Uri ORM/SOA command execution
- should return TRUE to execute the command, FALSE to cancel it
TOnErrorUri = function(Ctxt: TRestServerUriContext; E: Exception): boolean of object;
Callback raised if TRestServer.Uri execution failed
- should return TRUE to execute Ctxt.Error(E,...), FALSE if returned content has already been set as expected by the client
TOnInternalInfo = procedure(Sender: TRestUriContext; var Info: TDocVariantData) of object;
Callback allowing to customize the information returned by root/timestamp/info
- Sender is indeed a TRestServerUriContext instance
TOnOrmEvent = function(Sender: TRestServer; Event: TOrmEvent; aTable: TOrmClass; const aID: TID; const aSentData: RawUtf8): boolean of object;
Used to define how to trigger Events on record update
- see TRestServer.OnUpdateEvent property and InternalUpdateEvent() method
- returns true on success, false if an error occurred (but action must continue)
- to be used only server-side, not to synchronize some clients: the framework is designed around a stateless RESTful architecture (like HTTP/1.1), in which clients ask the server for refresh (see TRestClientUri.UpdateFromServer)
TOnOrmFieldEvent = function(Sender: TRestServer; Event: TOrmEvent; aTable: TOrmClass; const aID: TID; const aAffectedFields: TFieldBits): boolean of object;
Used to define how to trigger Events on record field update
- see TRestServer.OnBlobUpdateEvent property and InternalUpdateEvent() method
- returns true on success, false if an error occurred (but action must continue)
- to be used only server-side, not to synchronize some clients: the framework is designed around a stateless RESTful architecture (like HTTP/1.1), in which clients ask the server for refresh (see TRestClientUri.UpdateFromServer)
TOnOrmSession = function(Sender: TRestServer; Session: TAuthSession; Ctxt: TRestServerUriContext): boolean of object;
Session-related callbacks triggered by TRestServer
- for OnSessionCreate, returning TRUE will abort the session creation - and you can set Ctxt.Call^.OutStatus to a corresponding error code
TOnRestServerCallBack = procedure(Ctxt: TRestServerUriContext) of object;
Method prototype to be used on Server-Side for method-based services
- will be routed as ModelRoot/[TableName/TableID/]MethodName RESTful requests
- this mechanism is able to handle some custom Client/Server request, similar to the DataSnap technology, but in a KISS way; it's fully integrated in the Client/Server architecture of our framework
- just add a published method of this type to any TRestServer descendant
- when TRestServer.Uri receive a request for ModelRoot/MethodName or ModelRoot/TableName/TableID/MethodName, it will check for a published method in its self instance named MethodName which MUST be of TOnRestServerCallBack type (not checked neither at compile time neither at runtime: beware!) and call it to handle the request
- important warning: the method implementation MUST be thread-safe
- when TRestServer.Uri receive a request for ModelRoot/MethodName, it calls the corresponding published method with aRecord set to nil
- when TRestServer.Uri receive a request for ModelRoot/TableName/TableID/MethodName, it calls the corresponding published method with aRecord pointing to a just created instance of the corresponding class, with its field ID set; note that the only set field is ID: other fields of aRecord are not set, but must secificaly be retrieved on purpose
- for ModelRoot/TableName/TableID/MethodName, the just created instance will be freed by TRestServer.Uri when the method returns
- Ctxt.Call is set with low-level incoming and outgoing data from client (e.g. Ctxt.Call.InBody contain POST/PUT data message)
- Ctxt.Session* will identify to the authentication session of the remote client (CONST_AUTHENTICATION_NOT_USED=1 if authentication mode is not enabled or CONST_AUTHENTICATION_SESSION_NOT_STARTED=0 if the session not started yet) - code may use SessionGetUser() method to retrieve the user details
- Ctxt.Method will indicate the used HTTP verb (e.g. GET/POST/PUT..)
- if process succeeded, implementation shall call Ctxt.Results([]) method to set a JSON response object with one "result" field name or Ctxt.Returns([]) with a JSON object described in Name/Value pairs; if the returned value is not JSON_CONTENT_TYPE, use Ctxt.Returns() and its optional CustomHeader parameter can specify a custom header like TEXT_CONTENT_TYPE_HEADER
- if process succeeded, and no data is expected to be returned to the caller, implementation shall call overloaded Ctxt.Success() method with the expected status (i.e. just Ctxt.Success will return HTTP_SUCCESS)
- if process failed, implementation shall call Ctxt.Error() method to set the corresponding error message and error code number
- a typical implementation may be:
procedure TRestServerTest.Sum(Ctxt: TRestServerUriContext); begin Ctxt.Results([Ctxt.InputDouble['a'] + Ctxt.InputDouble['b']]); end;
- Client-Side can be implemented as you wish. By convention, it could be appropriate to define in either TRestServer (if to be called as ModelRoot/MethodName), either TOrm (if to be called as ModelRoot/TableName[/TableID]/MethodName) a custom public or protected method, calling TRestClientUri.URL with the appropriate parameters, and named (by convention) as MethodName; TRestClientUri has dedicated methods like CallBackGetResult, CallBackGet, CallBackPut and CallBack; see also TOrmModel.getURICallBack and JsonDecode function
function TOrmPeople.Sum(aClient: TRestClientUri; a, b: double): double; var err: integer; begin val(aClient.CallBackGetResult('sum', ['a', a, 'b', b]), result, err); end;
TOnRestServerClientCallback = function(aSender: TRestServer; const aInterfaceDotMethodName, aParams: RawUtf8; aConnectionID: TRestConnectionID; aFakeCallID: integer; aResult, aErrorMsg: PRawUtf8): boolean of object;
Event signature used to notify a client callback
- implemented e.g. by TRestHttpServer.NotifyCallback
TOnServiceCreateInstance = procedure( Sender: TServiceFactory; Instance: TInterfacedObject) of object;
Event signature used by TRestServer.OnServiceCreateInstance
- as called by TServiceFactoryServer.CreateInstance
- the actual Instance class can be quickly retrieved from TServiceFactoryServer(Sender).ImplementationClass
TOnStartUri = function(var Call: TRestUriParams): integer of object;
Callback raised when TRestServer.Uri start to process a request
- should return HTTP_SUCCESS (200) to continue, or an error code to abort
- could also change the Call fields on the fly, if needed
TOrmMonitorUsageClass = class of TOrmMonitorUsage;
Class-reference type (metaclass) of a TOrmMonitorUsage table
TRestHttpServerOption = ( rsoOnlyJsonRequests, rsoOnlyValidUtf8, rsoRedirectServerRootUriForExactCase, rsoAllowSingleServerNoRoot, rsoHeadersUnFiltered, rsoCompressSynLZ, rsoCompressGZip, rsoLogVerbose, rsoNoXPoweredHeader, rsoIncludeDateHeader, rsoBan40xIP, rsoEnableLogging, rsoTelemetryCsv, rsoTelemetryJson );
Customize TRestHttpServer process
- rsoOnlyJsonRequests will return HTTP 400 "Bad Request" if the input is not of 'application/json' content type
- rsoOnlyValidUtf8 will return HTTP 406 "Non Acceptable" if input JSON or text body is not valid UTF-8 - calling fast IsValidUtf8() function
- rsoRedirectServerRootUriForExactCase to search root URI case-sensitive, mainly to avoid errors with HTTP cookies, which path is case-sensitive - when set, such not exact case will be redirected via a HTTP 307 command
- rsoAllowSingleServerNoRoot will allow URI with no Model.Root prefix, i.e. 'GET url' to be handled as 'GET root/url' - by design, it would work only with a single registered TRestServer (to know which Model.Root to use)
- rsoHeadersUnFiltered maps THttpServer.HeadersUnFiltered property
- rsoCompressSynLZ and rsoCompressGZip enable SynLZ and GZip compression on server side - it should also be enabled for the client
- rsoLogVerbose would include a lot of detailed information, useful only to debug the low-level server process - to be enabled only when required
- rsoNoXPoweredHeader excludes 'X-Powered-By: mORMot 2 synopse.info' header
- rsoIncludeDateHeader will let all answers include a Date: ... HTTP header
- rsoBan40xIP will reject any IP for a few seconds after a 4xx error code is returned (but 401/403) - only implemented by socket servers for now
- rsoEnableLogging enable an associated THttpServerGeneric.Logger instance
- rsoTelemetryCsv and rsoTelemetryJson will enable CSV or JSON consolidated per-minute metrics logging via an associated THttpServerGeneric.Analyzer
TRestHttpServerOptions = set of TRestHttpServerOption;
How to customize TRestHttpServer process
TRestHttpServerRestAuthentication = ( adDefault, adHttpBasic, adWeak, adSspi );
Supported REST authentication schemes
- used by the overloaded TRestHttpServer.Create(TRestHttpServerDefinition) constructor in mormot.rest.http.server.pas, and also in dddInfraSettings.pas
- map TRestServerAuthenticationDefault, TRestServerAuthenticationHttpBasic, TRestServerAuthenticationNone and TRestServerAuthenticationSspi classes
- asSSPI will use mormot.lib.sspi/gssapi units depending on the OS, and may be not available on some targets (e.g. Android)
TRestNode = ( rnNone, rnTable, rnTableID, rnTableIDBlob, rnTableMethod, rnTableIDMethod, rnState, rnMethod, rnMethodPath, rnInterface, rnInterfaceClientID );
Kind of REST requests defined by TRestServer.ComputeRoutes for TRestTreeNode
- rnTable for ModelRoot/TableName GET POST PUT DELETE BEGIN END ABORT
- rnTableID for ModelRoot/TableName/<id> GET LOCK UNLOCK PUT DELETE
- rnTableIDBlob for ModelRoot/TableName/<id>/Blob GET PUT
- rnTableMethod for ModelRoot/TableName/MethodName GET POST PUT DELETE
- rnTableIDMethod ModelRoot/TableName/<id>/MethodName GET POST PUT DELETE
- rnState for ModelRoot STATE
- rnMethod for ModelRoot/MethodName GET POST PUT DELETE
- rnMethodPath for ModelRoot/MethodName/<path:fulluri> GET POST PUT DELETE
- rnInterface for ModelRoot/InterfaceName[/.InterfaceMethodName]
- rnInterfaceClientID for ModelRoot/InterfaceName/.InterfaceMethodName/<id>
TRestRouterTree = array[mGET .. high(TUriMethod)] of TRadixTreeParams;
Store per-method URI multiplexing Radix Tree in TRestRouter
- each HTTP method would have its dedicated TRestTree parser in TRestRouter
TRestServerAddStat = ( withTables, withMethods, withInterfaces, withSessions );
The flags used for TRestServer.AddStats
TRestServerAddStats = set of TRestServerAddStat;
Some flags used for TRestServer.AddStats
TRestServerAuthenticationClass = class of TRestServerAuthentication;
Class-reference type (metaclass) used to define an authentication scheme
TRestServerAuthenticationDynArray = array of TRestServerAuthentication;
Maintain a list of TRestServerAuthentication instances
TRestServerAuthenticationOption = ( saoUserByLogonOrID, saoHandleUnknownLogonAsStar );
Optional behavior of TRestServerAuthentication class
- by default, saoUserByLogonOrID is set, allowing TRestServerAuthentication.GetUser() to retrieve the TAuthUser by logon name or by ID, if the supplied logon name is an integer
- if saoHandleUnknownLogonAsStar is defined, any user successfully authenticated could be logged with the same ID (and authorization) than TAuthUser.Logon='*' - of course, this is meaningfull only with an external credential check (e.g. via SSPI or Active Directory)
TRestServerAuthenticationOptions = set of TRestServerAuthenticationOption;
Defines the optional behavior of TRestServerAuthentication class
TRestServerClass = class of TRestServer;
Class-reference type (metaclass) of a REST server
TRestServerKind = ( sMainEngine, sStaticDataTable, sVirtualTable );
Kind of (static) database server implementation available
- sMainEngine will identify the default main SQlite3 engine
- sStaticDataTable will identify a TRestStorageInMemory - i.e. TRestServer.fStaticData[] which can work without SQLite3
- sVirtualTable will identify virtual TRestStorage classes - i.e. TRestOrmServer.fStaticVirtualTable[] which points to SQLite3 virtual tables (e.g. TObjectList or external databases)
TRestServerMethods = array of TRestServerMethod;
Used to store all method-based services of a TRestServer instance
TRestServerMonitorLevels = set of ( mlUri, mlTables, mlMethods, mlInterfaces, mlSessions, mlSQLite3);
How TRestServer should maintain its statistical information
- used by TRestServer.StatLevels property
TRestServerOption = ( rsoNoAjaxJson, rsoGetAsJsonNotAsString, rsoGetID_str, rsoRedirectForbiddenToAuth, rsoHttp200WithNoBodyReturns204, rsoAddUpdateReturnsContent, rsoComputeFieldsBeforeWriteOnServerSide, rsoSecureConnectionRequired, rsoCookieIncludeRootPath, rsoCookieHttpOnlyFlagDisable, rsoAuthenticationUriDisable, rsoTimestampInfoUriDisable, rsoHttpHeaderCheckDisable, rsoGetUserRetrieveNoBlobData, rsoNoInternalState, rsoNoTableURI, rsoMethodUnderscoreAsSlashUri, rsoValidateUtf8Input, rsoSessionInConnectionOpaque );
Some options for TRestServer process
- read-only rsoNoAjaxJson indicates that JSON data is transmitted in "not expanded" format: you should NEVER change this option by including this property in TRestServer.Options, but always call explicitly TRestServer.NoAjaxJson := true so that the SetNoAjaxJson virtual method should be called as expected (e.g. to flush TRestServerDB cache)
- rsoGetAsJsonNotAsString will let ORM GET return to AJAX (non Delphi) clients JSON objects instead of the JSON text stored in database fields
- rsoGetID_str will add a "ID_str": string field to circumvent JavaScript limitation of 53-bit for integers - only for AJAX (non Delphi) clients
- unauthenticated requests from browsers (i.e. not Delphi clients) may be redirected to the TRestServer.Auth() method via rsoRedirectForbiddenToAuth (e.g. for TRestServerAuthenticationHttpBasic popup)
- some REST/AJAX clients may expect to return status code 204 instead of 200 in case of a successful operation, but with no returned body (e.g. DELETE with SAPUI5 / OpenUI5 framework): include rsoHttp200WithNoBodyReturns204 so that any HTTP_SUCCESS (200) with no returned body will return a HTTP_NOCONTENT (204), as expected by some clients
- by default, Add() or Update() will return HTTP_CREATED (201) or HTTP_SUCCESS (200) with no body, unless rsoAddUpdateReturnsContent is set to return as JSON the last inserted/updated record
- TModTime / TCreateTime fields are expected to be filled on client side, unless you set rsoComputeFieldsBeforeWriteOnServerSide so that AJAX requests will set the fields on the server side by calling the TOrm ComputeFieldsBeforeWrite virtual method, before writing to the database
- rsoSecureConnectionRequired will ensure Call is flagged as llfSecured (i.e. in-process, HTTPS, or encrypted WebSockets) - with the only exception of the Timestamp method-based service (for monitoring purposes) - note that this option doesn't make sense behind a proxy, just with a true HTTPS server
- by default, cookies will contain only 'Path=/Model.Root', but '; Path=/' may be also added setting rsoCookieIncludeRootPath
- you can disable the 'HttpOnly' flag via rsoCookieHttpOnlyFlagDisable
- TRestServerUriContext.AuthenticationBearerToken will return the ?authenticationbearer=... URI parameter value alternatively to the HTTP header unless rsoAuthenticationUriDisable is set (for security reasons)
- you can switch off root/timestamp/info URI via rsoTimestampInfoUriDisable
- Uri() header output will be sanitized for any EOL injection, unless rsoHttpHeaderCheckDisable is defined (to gain a few cycles)
- by default, TAuthUser.Data blob is retrieved from the database, unless rsoGetUserRetrieveNoBlobData is defined
- rsoNoInternalState could be state to avoid transmitting the 'Server-InternalState' header, e.g. if the clients wouldn't need it
- rsoNoTableURI will disable any /root/tablename URI for safety
- rsoMethodUnderscoreAsSlashUri will try to decode /root/method/name as 'method_name' method
- rsoValidateUtf8Input will call IsValidUtf8() on input UTF-8 JSON/text, to sanitize character encodings - with AVX2 this function is very fast so this could be a good option if you don't trust your clients
- rsoSessionInConnectionOpaque uses LowLevelConnectionOpaque^.ValueInternal to store the current TAuthSession - may be used with a lot of sessions
TRestServerOptions = set of TRestServerOption;
Allow to customize the TRestServer process via its Options property
TRestServerUriContextClass = class of TRestServerUriContext;
Class used to define the Server side expected routing
- match TRestClientRoutingClass reciprocal meta-class
- most of the internal methods are declared as virtual, so it allows any kind of custom routing or execution scheme
- TRestServerRoutingJsonRpc and TRestServerRoutingRest classes are provided in this unit, to allow RESTful and JSON/RPC protocols
TSqlRestServer = TRestServer;
Backward compatibility types redirections
HTTPSERVER_DEBUG_OPTIONS = [rsoCompressGZip, rsoCompressSynLZ, rsoLogVerbose];
TRestHttpServer processing options which may be used during raw debugging
HTTPSERVER_DEFAULT_OPTIONS = [rsoCompressGZip, rsoCompressSynLZ];
Default TRestHttpServer processing options are to support SynLZ and GZip
PAGINGPARAMETERS_YAHOO: TRestServerUriPagingParameters = ( Sort: 'SORT='; Dir: 'DIR='; StartIndex: 'STARTINDEX='; Results: 'RESULTS='; Select: 'SELECT='; Where: 'WHERE='; SendTotalRowsCountFmt: '');
The default URI parameters for query paging
- those values are the one expected by YUI components
SERVERDEFAULTMONITORLEVELS: TRestServerMonitorLevels = [mlUri, mlTables, mlMethods, mlInterfaces, mlSQLite3];
Default value of TRestServer.StatLevels property
- i.e. gather all statistics, but mlSessions which has a slowdown impact
| Functions or procedures | Description | |
|---|---|---|
| CurrentNonce | Returns a safe 256-bit nonce, changing every 5 minutes | |
| CurrentNonce | Returns a safe 256-bit hexadecimal nonce, changing every 5 minutes | |
| CurrentNonce256 | Returns a safe 256-bit nonce as binary, changing every 5 minutes | |
| IsCurrentNonce | Validate a 256-bit binary nonce against current or previous nonce | |
| IsCurrentNonce | Validate a 256-bit hexadecimal nonce against current or previous nonce | |
| LibraryRequest | This function can be exported from a DLL to remotely access to a TRestServer | |
| ServiceRunningContext | Returns the thread-specific service context execution currently running on the server side | |
| ServiceRunningRequest | Returns the thread-specific REST server execution context |
function CurrentNonce(Ctxt: TRestServerUriContext; Previous: boolean = false): RawUtf8; overload;
Returns a safe 256-bit hexadecimal nonce, changing every 5 minutes
- as used e.g. by TRestServerAuthenticationDefault.Auth
- this function is very fast, even if cryptographically-level SHA-3 secure
- Ctxt may be nil (only used for faster GetTickCount64)
procedure CurrentNonce(Ctxt: TRestServerUriContext; Previous: boolean; Nonce: PRawUtf8; Nonce256: PHash256; Tix64: Int64 = 0); overload;
Returns a safe 256-bit nonce, changing every 5 minutes
- can return the (may be cached) value as hexadecimal text or THash256 binary
function CurrentNonce256(Previous: boolean): THash256;
Returns a safe 256-bit nonce as binary, changing every 5 minutes
function IsCurrentNonce(Ctxt: TRestServerUriContext; const Nonce: RawUtf8): boolean; overload;
Validate a 256-bit hexadecimal nonce against current or previous nonce
function IsCurrentNonce(Ctxt: TRestServerUriContext; const Nonce256: THash256): boolean; overload;
Validate a 256-bit binary nonce against current or previous nonce
function LibraryRequest( Url, Method, SendData: PUtf8Char; UrlLen, MethodLen, SendDataLen: cardinal; out HeadRespFree: TLibraryRequestFree; var Head: PUtf8Char; var HeadLen: cardinal; out Resp: PUtf8Char; out RespLen, State: cardinal): cardinal; cdecl;
This function can be exported from a DLL to remotely access to a TRestServer
- use TRestServer.ExportServerGlobalLibraryRequest to assign a server to this function
- return the HTTP status, e.g. 501 HTTP_NOTIMPLEMENTED if no TRestServer.ExportServerGlobalLibraryRequest has been assigned yet
- once used, memory for Resp and Head should be released with LibraryRequestFree() returned function
- the Server current Internal State counter will be set to State
- simply use TRestClientLibraryRequest to access to an exported LibraryRequest() function
- match TLibraryRequest function signature
function ServiceRunningContext: PServiceRunningContext;
Returns the thread-specific service context execution currently running on the server side
- just an inlined transtype of the PerThreadRunningContextAddress function
- note that in case of direct server side execution of the service, this information won't be filled, so the safest (and slightly faster) access to the TRestServer instance associated with a service is to inherit your implementation class from TInjectableObjectRest, and not use this threadvar
- is set by TServiceFactoryServer.ExecuteMethod() just before calling the implementation method of a service, allowing to retrieve the current execution context - Request member is set from a client/server execution: Request.Server is the safe access point to the underlying TRestServer, in such context - also consider the CurrentServiceContextServer function to retrieve directly the running TRestServer (if any)
- its content is reset to zero out of the scope of a method execution
- when used, a local copy or a PServiceRunningContext pointer should better be created, since accessing a threadvar has a non negligible performance cost - for instance, if you want to use a "with" statement:
with ServiceRunningContext do ... access TServiceRunningContext members
or as a local variable:
var context: PServiceRunningContext; inContentType: RawUtf8; begin context := ServiceRunningContext; // threadvar access once ... inContentType := context.Request.Call^.InBodyType; end;
function ServiceRunningRequest: TRestServerUriContext;
Returns the thread-specific REST server execution context
- just a wrapper around ServiceRunningContext^.Request