logo.png
mORMot2 API Reference

mormot.net.server.pas unit

Purpose: HTTP/HTTPS Server Classes
- this unit is a part of the Open Source Synopse mORMot framework 2, licensed under a MPL/GPL/LGPL three license - see LICENSE.md

1.1. Units used in the mormot.net.server unit

Unit NameDescription
mormot.core.baseFramework Core Shared Types and RTL-like Functions
mormot.core.buffersFramework Core Low-Level Memory Buffer Process
mormot.core.dataFramework Core Low-Level Data Processing Functions
mormot.core.datetimeFramework Core Low-Level Date and Time Support
mormot.core.jsonFramework Core Low-Level JSON Processing
mormot.core.logFramework Core Logging
mormot.core.osFramework Core Low-Level Wrappers to the Operating-System API
mormot.core.rttiFramework Core Low-Level Cross-Compiler RTTI Definitions
mormot.core.searchFramework Core Text, Binary and Time Search Engines
mormot.core.textFramework Core Low-Level Text Processing
mormot.core.threadsFramework Core Multi-Threading Support
mormot.core.unicodeFramework Core Low-Level Unicode UTF-8 UTF-16 Ansi Conversion
mormot.core.zipFramework Core Zip/Deflate Compression Support
mormot.crypt.coreFramework Core Cryptographic Process (Hashing and Cypher)
mormot.crypt.secureFramework Core Authentication and Security Features
mormot.lib.winhttpWindows HTTP and WebSockets API Libraries
mormot.net.clientHTTP/HTTPS Client Classes
mormot.net.httpHTTP/HTTPS Abstract Process Classes and Definitions
mormot.net.sockLow-level access to the OperatingSystem Sockets API (e.g. WinSock2)

1.2. mormot.net.server class hierarchy

TThreadTSynWebSocketGuardTSynThreadPoolTSynThreadPoolTHttpServerTSynThreadPoolHttpApiWebSocketServerTSynThreadTHttpServerRespTSynPersistentRWLightLockTUriRouterTSynPersistentTHttpPeerCacheSettingsTHttpPeerCacheProcessTRadixTreeParamsTUriTreeTRadixTreeNodeParamsTUriTreeNodeTObjectTHttpApiWebSocketServerProtocolTHttpApiWebSocketConnectionTHttpServerSocketGenericTHttpServerTHttpServerGenericTHttpApiServerTHttpApiWebSocketServerTNotifiedThreadTUdpServerThreadTHttpPeerCacheThreadTLoggedThreadTHttpPeerCryptTHttpPeerCacheTInterfacedObjectWithCustomCreateTHttpSocketTHttpServerSocketTHttpServerRequestAbstractTHttpServerRequestESynExceptionEHttpServerEHttpPeerCacheERadixTreeEUriRouterENetSockEUdpServer
mormot.net.server class hierarchy

1.3. Objects implemented in the mormot.net.server unit

ObjectsDescription
EHttpPeerCacheException class raised on THttpPeerCache issues
EHttpServerException raised during HTTP process
EUriRouterException class raised during TUriRouter.Rewrite/Run registration
THttpApiServerHTTP server using fast http.sys kernel-mode server
THttpApiWebSocketConnectionStructure representing a single WebSocket connection
THttpApiWebSocketServerHTTP & WebSocket server using fast http.sys kernel-mode server
THttpApiWebSocketServerProtocolProtocol Handler of websocket endpoints events
THttpPeerCacheImplement a local peer-to-peer download cache via UDP and TCP
THttpPeerCacheHashStore a hash value and its algorithm, for THttpPeerCacheMessage.Hash
THttpPeerCacheMessageOne UDP request frame used during THttpPeerCache discovery
THttpPeerCacheProcessOne THttpPeerCache.OnDownload instance
THttpPeerCacheSettingsDefine how THttpPeerCache handles its process
THttpPeerCacheThreadBackground UDP server thread, associated to a THttpPeerCache instance
THttpPeerCryptAbstract parent to THttpPeerCache for its cryptographic core
THttpServerMain HTTP server Thread using the standard Sockets API (e.g. WinSock)
THttpServerGenericAbstract parent class to implement a HTTP server
THttpServerRequestA generic input/output structure used for HTTP server requests
THttpServerRespHTTP response Thread as used by THttpServer Socket API based class
THttpServerSocketSocket API based HTTP/1.1 server class used by THttpServer Threads
THttpServerSocketGenericAbstract parent class for both THttpServer and THttpAsyncServer
TSynThreadPoolHttpApiWebSocketServerA Thread Pool, used for fast handling of WebSocket requests
TSynThreadPoolTHttpServerA simple Thread Pool, used for fast handling HTTP requests of a THttpServer
TSynWebSocketGuardThread for closing deprecated WebSocket connections
TUdpServerThreadAbstract UDP server thread
TUriRouterEfficient server-side URI routing for THttpServerGeneric
TUriTreeImplement a Radix Tree to hold all registered URI for a given HTTP method
TUriTreeNodeImplement a Radix Tree node to hold one URI registration
TUriTreeNodeDataContext information, as cloned by TUriTreeNode.Split()

1.3.1. TUdpServerThread

TUdpServerThread = class(TLoggedThread)

Abstract UDP server thread


constructor Create(LogClass: TSynLogClass; const BindAddress, BindPort, ProcessName: RawUtf8; TimeoutMS: integer); reintroduce;

Initialize and bind the server instance, in non-suspended state


destructor Destroy; override;

Finalize the processing thread


1.3.2. TUriTreeNodeData

TUriTreeNodeData = record

Context information, as cloned by TUriTreeNode.Split()


Execute: TOnHttpServerRequest;

The callback registered by Run() for this URI


ExecuteOpaque: pointer;

An additional pointer value, assigned to Ctxt.RouteOpaque of Execute()


ToUri: RawUtf8;

The Rewrite() URI text


ToUriErrorStatus: word ;

The HTTP error code for a Rewrite() with an integer ToUri (e.g. '404')


ToUriMethod: TUriRouterMethod;

The URI method to be used after ToUri rewrite


ToUriPosLen: TIntegerDynArray;

[pos1,len1,valndx1,pos2,len2,valndx2,...] trios from ToUri content


ToUriStaticLen: integer;

The size of all ToUriPosLen[] static content


1.3.3. TUriTreeNode

TUriTreeNode = class(TRadixTreeNodeParams)

Implement a Radix Tree node to hold one URI registration


Data: TUriTreeNodeData;

All context information, as cloned by Split()


function Split(const Text: RawUtf8): TRadixTreeNode; override;

Overriden to support the additional Data fields


1.3.4. TUriTree

TUriTree = class(TRadixTreeParams)

Implement a Radix Tree to hold all registered URI for a given HTTP method


function Root: TUriTreeNode;

Access to the root node of this tree


1.3.5. EUriRouter

EUriRouter = class(ERadixTree)

Exception class raised during TUriRouter.Rewrite/Run registration


1.3.6. TUriRouter

TUriRouter = class(TSynPersistentRWLightLock)

Efficient server-side URI routing for THttpServerGeneric
- Process() is done with no memory allocation for a static route, using a very efficient Radix Tree for path lookup, over a thread-safe non-blocking URI parsing with values extractions for rewrite or execution
- here are some numbers from TNetworkProtocols._TUriTree on my laptop:

 1000 URI lookups in 37us i.e. 25.7M/s, aver. 37ns
 1000 URI static rewrites in 80us i.e. 11.9M/s, aver. 80ns
 1000 URI parametrized rewrites in 117us i.e. 8.1M/s, aver. 117ns
 1000 URI static execute in 91us i.e. 10.4M/s, aver. 91ns
 1000 URI parametrized execute in 162us i.e. 5.8M/s, aver. 162ns

constructor Create(aNodeClass: TRadixTreeNodeClass; aOptions: TRadixTreeOptions = []); reintroduce;

Initialize this URI routing engine


destructor Destroy; override;

Finalize this URI routing engine


function Lookup(const aUri, aUriMethod: RawUtf8): TUriTreeNode;

Search for a given URI match
- could be used e.g. in OnBeforeBody() to quickly reject an invalid URI
- this method is thread-safe


function Process(Ctxt: THttpServerRequestAbstract): integer;

Perform URI parsing and rewrite/execution within HTTP server Ctxt members
- should return 0 to continue the process, on a HTTP status code to abort if the request has been handled by a TOnHttpServerRequest callback
- this method is thread-safe


procedure Clear(aMethods: TUriRouterMethods = [urmGet .. high(TUriRouterMethod)]);

Erase all previous registrations, optionally for a given HTTP method
- currently, there is no way to delete a route once registered, to optimize the process thread-safety: use Clear then re-register


procedure Delete(const aUri: RawUtf8; const aExecute: TOnHttpServerRequest; aExecuteOpaque: pointer = nil); overload;

Just a wrapper around Run([urmDelete], aUri, aExecute) registration method


procedure Delete(const aFrom, aTo: RawUtf8; aToMethod: TUriRouterMethod = urmDelete); overload;

Just a wrapper around Rewrite(urmDelete, aFrom, aToMethod, aTo)
- e.g. Route.Delete('/doremove', '/root/myservice/delete', urmPost);


procedure Get(const aFrom, aTo: RawUtf8; aToMethod: TUriRouterMethod = urmGet); overload;

Just a wrapper around Rewrite(urmGet, aFrom, aToMethod, aTo)
- e.g. Route.Get('/info', 'root/timestamp/info');
- e.g. Route.Get('/user/<id>', '/root/userservice/new?id=<id>'); will rewrite internally '/user/1234' URI as '/root/userservice/new?id=1234'
- e.g. Route.Get('/user/<int:id>', '/root/userservice/new?id=<id>'); to ensure id is a real integer before redirection
- e.g. Route.Get('/admin.php', '403');
- e.g. Route.Get('/*', '/static/*'); with '*' synonymous to '<path:path>'


procedure Get(const aUri: RawUtf8; const aExecute: TOnHttpServerRequest; aExecuteOpaque: pointer = nil); overload;

Just a wrapper around Run([urmGet], aUri, aExecute) registration method
- e.g. Route.Get('/plaintext', DoPlainText);


procedure Head(const aUri: RawUtf8; const aExecute: TOnHttpServerRequest; aExecuteOpaque: pointer = nil); overload;

Just a wrapper around Run([urmHead], aUri, aExecute) registration method


procedure Head(const aFrom, aTo: RawUtf8; aToMethod: TUriRouterMethod = urmHead); overload;

Just a wrapper around Rewrite(urmHead, aFrom, aToMethod, aTo)
- e.g. Route.Head('/doremove', '/root/myservice/Head', urmPost);


procedure Options(const aFrom, aTo: RawUtf8; aToMethod: TUriRouterMethod = urmOptions); overload;

Just a wrapper around Rewrite(urmOptions, aFrom, aToMethod, aTo)
- e.g. Route.Options('/doremove', '/root/myservice/Options', urmPost);


procedure Options(const aUri: RawUtf8; const aExecute: TOnHttpServerRequest; aExecuteOpaque: pointer = nil); overload;

Just a wrapper around Run([urmOptions], aUri, aExecute) registration method


procedure Post(const aUri: RawUtf8; const aExecute: TOnHttpServerRequest; aExecuteOpaque: pointer = nil); overload;

Just a wrapper around Run([urmPost], aUri, aExecute) registration method


procedure Post(const aFrom, aTo: RawUtf8; aToMethod: TUriRouterMethod = urmPost); overload;

Just a wrapper around Rewrite(urmPost, aFrom, aToMethod, aTo)
- e.g. Route.Post('/doconvert', '/root/myservice/convert');


procedure Put(const aFrom, aTo: RawUtf8; aToMethod: TUriRouterMethod = urmPut); overload;

Just a wrapper around Rewrite(urmPut, aFrom, aToMethod, aTo)
- e.g. Route.Put('/domodify', '/root/myservice/update', urmPost);


procedure Put(const aUri: RawUtf8; const aExecute: TOnHttpServerRequest; aExecuteOpaque: pointer = nil); overload;

Just a wrapper around Run([urmPut], aUri, aExecute) registration method


procedure Rewrite(aFrom: TUriRouterMethod; const aFromUri: RawUtf8; aTo: TUriRouterMethod; const aToUri: RawUtf8);

Register an URI rewrite with optional <param> place holders
- <param> will be replaced in aToUri
- if aToUri is an '200'..'599' integer, it will return it as HTTP error
- otherwise, the URI will be rewritten into aToUri, e.g.

 Rewrite(urmGet, '/info', urmGet, 'root/timestamp/info');
 Rewrite(urmGet, '/path/from/<from>/to/<to>', urmPost,
  '/root/myservice/convert?from=<from>&to=<to>'); // for IMyService.Convert
 Rewrite(urmGet, '/index.php', '400'); // to avoid fuzzing
 Rewrite(urmGet, '/*', '/static/*' // '*' synonymous to '<path:path>'

procedure Run(aFrom: TUriRouterMethods; const aFromUri: RawUtf8; const aExecute: TOnHttpServerRequest; aExecuteOpaque: pointer = nil);

Assign a TOnHttpServerRequest callback with a given URI
- <param> place holders will be parsed and available in callback as Ctxt['param'] default property or Ctxt.RouteInt64/RouteEquals methods
- could be used e.g. for standard REST process as

 Route.Run([urmGet], '/user/<user>/pic', DoUserPic) // retrieve a list
 Route.Run([urmGet, urmPost, urmPut, urmDelete],
    '/user/<user>/pic/<id>', DoUserPic) // CRUD picture access

procedure RunMethods(RouterMethods: TUriRouterMethods; Instance: TObject; const Prefix: RawUtf8 = '/');

Assign the published methods of a class instance to their URI via RTTI
- the signature of each method should match TOnHttpServerRequest
- the method name is used for the URI, e.g. Instance.user as '/user', with exact case matching, and replacing _ in the method name by '-', e.g. Instance.cached_query as '/cached-query'


property Deletes: integer read fEntries[urmDelete];

How many DELETE rules have been registered


property Gets: integer read fEntries[urmGet];

How many GET rules have been registered


property Heads: integer read fEntries[urmHead];

How many HEAD rules have been registered


property Optionss: integer read fEntries[urmOptions];

How many OPTIONS rules have been registered


property Posts: integer read fEntries[urmPost];

How many POST rules have been registered


property Puts: integer read fEntries[urmPut];

How many PUT rules have been registered


property Tree: TUriRouterTree read fTree;

Access to the internal per-method TUriTree instance
- some Tree[] may be nil if the HTTP method has not been registered yet
- used only for testing/validation purpose


property TreeOptions: TRadixTreeOptions read fTreeOptions write fTreeOptions;

How the TUriRouter instance should be created
- should be set before calling Run/Rewrite registration methods


1.3.7. EHttpServer

EHttpServer = class(ESynException)

Exception raised during HTTP process


1.3.8. THttpServerRequest

THttpServerRequest = class(THttpServerRequestAbstract)

A generic input/output structure used for HTTP server requests
- URL/Method/InHeaders/InContent properties are input parameters
- OutContent/OutContentType/OutCustomHeader are output parameters


constructor Create(aServer: THttpServerGeneric; aConnectionID: THttpServerConnectionID; aConnectionThread: TSynThread; aConnectionFlags: THttpServerRequestFlags; aConnectionOpaque: PHttpServerConnectionOpaque); virtual;

Initialize the context, associated to a HTTP server instance


destructor Destroy; override;

Finalize this execution context


function RouteOpaque: pointer; override;

An additional custom parameter, as provided to TUriRouter.Setup


function SetAsyncResponse: integer;

Notify the server that it should wait for the OnAsyncResponse callback
- would raise an EHttpServer exception if OnAsyncResponse is not set
- returns HTTP_ASYNCRESPONSE (777) internal code as recognized e.g. by THttpAsyncServer


function SetupResponse(var Context: THttpRequestContext; CompressGz, MaxSizeAtOnce: integer): PRawByteStringBuffer;

Prepare one reusable HTTP State Machine for sending the response


function TempJsonWriter(var temp: TTextWriterStackBuffer): TJsonWriter;

Low-level initialization of the associated TJsonWriter instance
- will reset and reuse an TJsonWriter associated to this execution context
- as called by SetOutJson() oveloaded methods using RTTI
- a local TTextWriterStackBuffer should be provided as temporary buffer


procedure Recycle(aConnectionID: THttpServerConnectionID; aConnectionThread: TSynThread; aConnectionFlags: THttpServerRequestFlags; aConnectionOpaque: PHttpServerConnectionOpaque);

Could be called before Prepare() to reuse an existing instance


procedure SetErrorMessage(const Fmt: RawUtf8; const Args: array of const);

Just a wrapper around fErrorMessage := FormatString()


procedure SetOutJson(Value: pointer; TypeInfo: PRttiInfo); overload;

Serialize a given value as JSON into OutContent and OutContentType fields


procedure SetOutJson(Value: TObject); overload;

Serialize a given TObject as JSON into OutContent and OutContentType fields


property ErrorMessage: string read fErrorMessage write fErrorMessage;

Optional error message which will be used by SetupResponse


property FullUrl: SynUnicode read GetFullUrl;

For THttpApiServer, input parameter containing the caller full URL


property HttpApiRequest: PHTTP_REQUEST read fHttpApiRequest;

For THttpApiServer, points to a PHTTP_REQUEST structure


property OnAsyncResponse: TOnHttpServerRequestAsyncResponse read fOnAsyncResponse write fOnAsyncResponse;

A callback used for asynchronous response to the client
- only implemented by the THttpAsyncServer by now


property Server: THttpServerGeneric read fServer;

The associated server instance
- may be a THttpServer or a THttpApiServer class


1.3.9. THttpServerGeneric

THttpServerGeneric = class(TNotifiedThread)

Abstract parent class to implement a HTTP server
- do not use it, but rather THttpServer/THttpAsyncServer or THttpApiServer


constructor Create(const OnStart, OnStop: TOnNotifyThread; const ProcessName: RawUtf8; ProcessOptions: THttpServerOptions); reintroduce; virtual;

Initialize the server instance


destructor Destroy; override;

Release all memory and handlers used by this server


function Callback(Ctxt: THttpServerRequest; aNonBlocking: boolean): cardinal; virtual;

Server can send a request back to the client, when the connection has been upgraded e.g. to WebSockets
- InURL/InMethod/InContent properties are input parameters (InContentType is ignored)
- OutContent/OutContentType/OutCustomHeader are output parameters
- Ctxt.ConnectionID should be set, so that the method could know which connnection is to be used - returns HTTP_NOTFOUND (404) if unknown
- result of the function is the HTTP error code (200 if OK, e.g.)
- warning: this void implementation will raise an EHttpServer exception - inherited classes should override it, e.g. as in TWebSocketServerRest


function CanNotifyCallback: boolean;

TRUE if the inherited class is able to handle callbacks
- only TWebSocketServer/TWebSocketAsyncServer have this ability by now


function ReplaceRoute(another: TUriRouter): TUriRouter;

Thread-safe replace the TUriRouter instance
- returns the existing instance: caller should keep it for a few seconds untouched prior to Free it, to let finish any pending background process


function Request(Ctxt: THttpServerRequestAbstract): cardinal; virtual;

Override this function to customize your http server
- InURL/InMethod/InContent properties are input parameters
- OutContent/OutContentType/OutCustomHeader are output parameters
- result of the function is the HTTP error code (200 if OK, e.g.),
- OutCustomHeader is available to handle Content-Type/Location
- if OutContentType is STATICFILE_CONTENT_TYPE (i.e. '!STATICFILE'), then OutContent is the UTF-8 filename of a file to be sent directly to the client via http.sys or NGINX's X-Accel-Redirect; the OutCustomHeader should contain the eventual 'Content-type: ....' value
- default implementation is to call the OnRequest event (if existing), and will return HTTP_NOTFOUND if OnRequest was not set
- warning: this process must be thread-safe (can be called by several threads simultaneously, but with a given Ctxt instance for each)


function Route: TUriRouter;

Specify URI routes for internal URI rewrites or callback execution
- rules registered here will be processed before main Request/OnRequest
- URI rewrites allow to extend the default routing, e.g. from TRestServer
- callbacks execution allow efficient server-side processing with parameters
- static routes could be defined e.g. Route.Get('/', '/root/default')
- <param> place holders could be defined for proper URI rewrite e.g. Route.Post('/user/<id>', '/root/userservice/new?id=<id>') will rewrite internally '/user/1234' URI as '/root/userservice/new?id=1234'
- could be used e.g. for standard REST process via event callbacks with Ctxt['user'] or Ctxt.RouteInt64('id') parameter extraction in DoUserPic:

 Route.Run([urmGet], '/user/<user>/pic', DoUserPic) // retrieve a list
 Route.Run([urmGet, urmPost, urmPut, urmDelete],
    '/user/<user>/pic/<id>', DoUserPic) // CRUD picture access

- warning: with the THttpApiServer, URIs will be limited by the actual root URI registered at http.sys level - there is no such limitation with the socket servers, which bind to a port, so handle all URIs on it


procedure RegisterCompress(aFunction: THttpSocketCompress; aCompressMinSize: integer = 1024; aPriority: integer = 10); virtual;

Will register a compression algorithm
- used e.g. to compress on the fly the data, with standard gzip/deflate or custom (synlz) protocols
- you can specify a minimal size (in bytes) before which the content won't be compressed (1024 by default, corresponding to a MTU of 1500 bytes)
- the first registered algorithm will be the prefered one for compression within each priority level (the lower aPriority first)


procedure SetFavIcon(const FavIconContent: RawByteString = 'default');

Will route a GET to /favicon.ico to the given .ico file content
- if none is supplied, the default Synopse/mORMot icon is used
- if '' is supplied, /favicon.ico will return a 404 error status
- warning: with THttpApiServer, may require a proper URI registration


procedure Shutdown;

You can call this method to prepare the HTTP server for shutting down


property Analyzer: THttpAnalyzer read fAnalyzer;

Access to the HTTP analyzer initialized with hsoTelemetryCsv or hsoTelemetryJson options
- you can customize this process via Analyzer.DestFolder


property ApiVersion: RawUtf8 read GetApiVersion;

Returns the API version used by the inherited implementation


property ConnectionsActive: cardinal read GetConnectionsActive;

Returns the number of current HTTP connections
- may not include HTTP/1.0 short-living connections


property HttpQueueLength: cardinal read GetHttpQueueLength write SetHttpQueueLength;

Defines request/response internal queue length
- default value if 1000, which sounds fine for most use cases
- for THttpApiServer, will return 0 if the system does not support HTTP API 2.0 (i.e. under Windows XP or Server 2003)
- for THttpServer or THttpAsyncServer, will shutdown any incoming accepted socket if the internal number of pending requests exceed this limit
- increase this value if you don't have any load-balancing in place, and in case of e.g. many 503 HTTP answers or if many "QueueFull" messages appear in HTTP.sys log files (normally in C:\Windows\System32\LogFiles\HTTPERR\httperr*.log) - may appear with thousands of concurrent clients accessing at once the same server - see @http://msdn.microsoft.com/en-us/library/windows/desktop/aa364501
- you can use this property with a reverse-proxy as load balancer, e.g. with nginx configured as such:

 location / {
       proxy_pass              http://balancing_upstream;
       proxy_next_upstream     error timeout invalid_header http_500 http_503;
       proxy_connect_timeout   2;
       proxy_set_header        Host            $host;
       proxy_set_header        X-Real-IP       $remote_addr;
       proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;
       proxy_set_header        X-Conn-ID       $connection
 }

see https://synopse.info/forum/viewtopic.php?pid=28174#p28174


property Logger: THttpLogger read fLogger;

Access to the HTTP logger initialized with hsoEnableLogging option
- you can customize the logging process via Logger.Format, Logger.DestFolder, Logger.DefaultRotate, Logger.DefaultRotateFiles properties and Logger.DefineHost() method
- equals nil if hsoEnableLogging was not set in the constructor


property MaximumAllowedContentLength: cardinal read fMaximumAllowedContentLength write SetMaximumAllowedContentLength;

Reject any incoming request with a body size bigger than this value
- default to 0, meaning any input size is allowed
- returns HTTP_PAYLOADTOOLARGE = 413 error if "Content-Length" incoming header overflow the supplied number of bytes


property OnAfterRequest: TOnHttpServerRequest read fOnAfterRequest write SetOnAfterRequest;

Event handler called after request is processed but before response is sent back to client
- main purpose is to apply post-processor, not part of request logic
- if handler returns value > 0 it will override the OnRequest response code
- warning: this handler must be thread-safe (could be called from several threads), and is NOT called after Route() callbacks execution


property OnAfterResponse: TOnHttpServerAfterResponse read fOnAfterResponse write SetOnAfterResponse;

Event handler called after response is sent back to client
- main purpose is to apply post-response analysis, logging, etc...
- warning: this handler must be thread-safe (could be called from several threads), and IS called after Route() callbacks execution


property OnBeforeBody: TOnHttpServerBeforeBody read fOnBeforeBody write SetOnBeforeBody;

Event handler called just before the body is retrieved from the client
- should return HTTP_SUCCESS=200 to continue the process, or an HTTP error code to reject the request immediately, and close the connection


property OnBeforeRequest: TOnHttpServerRequest read fOnBeforeRequest write SetOnBeforeRequest;

Event handler called after HTTP body has been retrieved, before OnRequest
- may be used e.g. to return a HTTP_ACCEPTED (202) status to client and continue a long-term job inside the OnRequest handler in the same thread; or to modify incoming information before passing it to main business logic, (header preprocessor, body encoding etc...)
- if the handler returns > 0 server will send a response immediately, unless return code is HTTP_ACCEPTED (202), then OnRequest will be called
- warning: this handler must be thread-safe (could be called from several threads), and is NOT called before Route() callbacks execution


property OnHttpThreadStart: TOnNotifyThread read fOnThreadStart write fOnThreadStart;

Event handler called after each working Thread is just initiated
- called in the thread context at first place in THttpServerGeneric.Execute


property OnHttpThreadTerminate: TOnNotifyThread read fOnThreadTerminate write SetOnTerminate;

Event handler called when a working Thread is terminating
- called in the corresponding thread context
- the TThread.OnTerminate event will be called within a Synchronize() wrapper, so it won't fit our purpose
- to be used e.g. to call CoUnInitialize from thread in which CoInitialize was made, for instance via a method defined as such:

 procedure TMyServer.OnHttpThreadTerminate(Sender: TThread);
 begin // TSqlDBConnectionPropertiesThreadSafe
   fMyConnectionProps.EndCurrentThread;
 end;

- is used e.g. by TRest.EndCurrentThread for proper multi-threading


property OnRequest: TOnHttpServerRequest read fOnRequest write SetOnRequest;

Main event handler called by the default implementation of the virtual Request method to process a given request
- OutCustomHeader will handle Content-Type/Location
- if OutContentType is STATICFILE_CONTENT_TYPE (i.e. '!STATICFILE'), then OutContent is the UTF-8 filename of a file to be sent directly to the client via http.sys or NGINX's X-Accel-Redirect; the OutCustomHeader should contain the eventual 'Content-type: ....' value
- warning: this process must be thread-safe (can be called by several threads simultaneously)


property OnSendFile: TOnHttpServerSendFile read fOnSendFile write fOnSendFile;

Custom event handler used to send a local file for STATICFILE_CONTENT_TYPE
- see also NginxSendFileFrom() method


property Options: THttpServerOptions read fOptions write SetOptions;

Allow to customize this HTTP server instance
- some inherited classes may have only partial support of those options


property ProcessName: RawUtf8 read fProcessName write fProcessName;

The associated process name


property RemoteConnIDHeader: RawUtf8 read fRemoteConnIDHeader write SetRemoteConnIDHeader;

The value of a custom HTTP header containing the real client connection ID
- by default, Ctxt.ConnectionID information will be retrieved from our socket layer - but if the server runs behind some proxy service, you should define here the HTTP header name which indicates the real remote connection, for example as 'X-Conn-ID', setting in nginx config:

 proxy_set_header      X-Conn-ID       $connection

property RemoteIPHeader: RawUtf8 read fRemoteIPHeader write SetRemoteIPHeader;

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 Router: TUriRouter read fRoute;

Read access to the URI router, as published property (e.g. for logs)
- use the Route function to actually setup the routing
- may be nil if Route has never been accessed, i.e. no routing was set


property RouterClass: TRadixTreeNodeClass read fRouterClass write SetRouterClass;

Allow to customize the Route() implementation Radix Tree node class
- if not set, will use TUriTreeNode as defined in this unit
- raise an Exception if set twice, or after Route() is called


property ServerName: RawUtf8 read fServerName write SetServerName;

The Server name, UTF-8 encoded, e.g. 'mORMot2 (Linux)'
- will be served as "Server: ..." HTTP header
- for THttpApiServer, when called from the main instance, will propagate the change to all cloned instances, and included in any HTTP API 2.0 log


1.3.10. THttpServerSocket

THttpServerSocket = class(THttpSocket)

Socket API based HTTP/1.1 server class used by THttpServer Threads


constructor Create(aServer: THttpServer); reintroduce;

Create the socket according to a server
- will register the THttpSocketCompress functions from the server
- once created, caller should call AcceptRequest() to accept the socket
- if TLS is enabled, ensure server certificates are initialized once


function GetConnectionOpaque: PHttpServerConnectionOpaque;

Access to the internal two PtrUInt tags of this connection
- may be nil behind a reverse proxy (i.e. Server.RemoteConnIDHeader<>'')


function GetRequest(withBody: boolean; headerMaxTix: Int64): THttpServerSocketGetRequestResult; virtual;

Main object function called after aClientSock := Accept + Create:
- get Command, Method, URL, Headers and Body (if withBody is TRUE)
- get sent data in Content (if withBody=true and ContentLength<>0)
- returned enumeration will indicates the processing state


property KeepAliveClient: boolean read fKeepAliveClient write fKeepAliveClient;

True if the client is HTTP/1.1 and 'Connection: Close' is not set
- default HTTP/1.1 behavior is "keep alive", unless 'Connection: Close' is specified, cf. RFC 2068 page 108: "HTTP/1.1 applications that do not support persistent connections MUST include the "close" connection option in every message"


property Method: RawUtf8 read Http.CommandMethod;

Contains the method ('GET','POST'.. e.g.) after GetRequest()


property RemoteConnectionID: THttpServerConnectionID read fRemoteConnectionID;

The recognized connection ID, after a call to GetRequest()
- identifies either the raw connection on the current server, or the custom header value as set by a local proxy, e.g. THttpServerGeneric.RemoteConnIDHeader='X-Conn-ID' for nginx


property Server: THttpServer read fServer;

The associated HTTP Server instance - may be nil


property URL: RawUtf8 read Http.CommandUri;

Contains the URL ('/' e.g.) after GetRequest()


1.3.11. THttpServerResp

THttpServerResp = class(TSynThread)

HTTP response Thread as used by THttpServer Socket API based class
- Execute procedure get the request and calculate the answer, using the thread for a single client connection, until it is closed
- you don't have to overload the protected THttpServerResp Execute method: override THttpServer.Request() function or, if you need a lower-level access (change the protocol, e.g.) THttpServer.Process() method itself


constructor Create(aServerSock: THttpServerSocket; aServer: THttpServer); reintroduce; overload; virtual;

Initialize the response thread for the corresponding incoming socket
- this version will handle KeepAlive, for such an incoming request


constructor Create(aSock: TNetSocket; const aSin: TNetAddr; aServer: THttpServer); reintroduce; overload;

Initialize the response thread for the corresponding incoming socket
- this version will get the request directly from an incoming socket


procedure Shutdown; virtual;

Called by THttpServer.Destroy on existing connections
- set Terminate and close the socket


property ConnectionID: THttpServerConnectionID read fConnectionID;

The unique identifier of this connection


property Server: THttpServer read fServer;

The associated main HTTP server instance


property ServerSock: THttpServerSocket read fServerSock;

The associated socket to communicate with the client


1.3.12. TSynThreadPoolTHttpServer

TSynThreadPoolTHttpServer = class(TSynThreadPool)

A simple Thread Pool, used for fast handling HTTP requests of a THttpServer
- will handle multi-connection with less overhead than creating a thread for each incoming request
- will create a THttpServerResp response thread, if the incoming request is identified as HTTP/1.1 keep alive, or HTTP body length is bigger than 1 MB


constructor Create(Server: THttpServer; NumberOfThreads: integer = 32); reintroduce;

Initialize a thread pool with the supplied number of threads
- Task() overridden method processs the HTTP request set by Push()
- up to 256 threads can be associated to a Thread Pool


property BigBodySize: integer read fBigBodySize write fBigBodySize;

When Content-Length is bigger than this value, by-pass the threadpool and creates a dedicated THttpServerResp thread
- default is THREADPOOL_BIGBODYSIZE = 16 MB, but can set a bigger value e.g. behind a buffering proxy if you trust the client not to make DOD


property MaxBodyThreadCount: integer read fMaxBodyThreadCount write fMaxBodyThreadCount;

How many stand-alone THttpServerResp threads can be initialized when a HTTP request comes in
- default is THREADPOOL_MAXWORKTHREADS = 512, but since each thread consume system memory, you should not go so high
- above this value, the thread pool will be used


1.3.13. THttpServerSocketGeneric

THttpServerSocketGeneric = class(THttpServerGeneric)

Abstract parent class for both THttpServer and THttpAsyncServer


constructor Create(const aPort: RawUtf8; const OnStart, OnStop: TOnNotifyThread; const ProcessName: RawUtf8; ServerThreadPoolCount: integer = 32; KeepAliveTimeOut: integer = 30000; ProcessOptions: THttpServerOptions = []); reintroduce; virtual;

Create a Server Thread, ready to be bound and listening on a port
- this constructor will raise a EHttpServer exception if binding failed
- expects the port to be specified as string, e.g. '1234'; you can optionally specify a server address to bind to, e.g. '1.2.3.4:1234'
- can listed to local Unix Domain Sockets file in case port is prefixed with 'unix:', e.g. 'unix:/run/myapp.sock' - faster and safer than TCP
- on Linux in case aPort is empty string will check if external fd is passed by systemd and use it (so called systemd socked activation)
- you can specify a number of threads to be initialized to handle incoming connections. Default is 32, which may be sufficient for most cases, maximum is 256. If you set 0, the thread pool will be disabled and one thread will be created for any incoming connection
- you can also tune (or disable with 0) HTTP/1.1 keep alive delay and how incoming request Headers[] are pushed to the processing method
- this constructor won't actually do the port binding, which occurs in the background thread: caller should therefore call WaitStarted after THttpServer.Create()


function AuthorizeServerMem: TDigestAuthServerMem;

Set after a call to SetAuthDigest/SetAuthBasic
- return nil if no such call was made, or not with a TDigestAuthServerMem
- return a TDigestAuthServerMem so that SetCredential/GetUsers are available


function WebSocketsEnable( const aWebSocketsURI, aWebSocketsEncryptionKey: RawUtf8; aWebSocketsAjax: boolean = false; aWebSocketsBinaryOptions: TWebSocketProtocolBinaryOptions = [pboSynLzCompress]): pointer; virtual;

Defines the WebSockets protocols to be used for this Server
- this default implementation will raise an exception
- returns the associated PWebSocketProcessSettings reference on success


procedure InitializeTlsAfterBind;

Could be called after WaitStarted(seconds,'','','') to setup TLS
- validate Sock.TLS.CertificateFile/PrivateKeyFile/PrivatePassword
- otherwise TLS is initialized at first incoming connection, which could be too late in case of invalid Sock.TLS parameters


procedure NginxSendFileFrom(const FileNameLeftTrim: TFileName);

Enable NGINX X-Accel internal redirection for STATICFILE_CONTENT_TYPE
- will define internally a matching OnSendFile event handler
- generating "X-Accel-Redirect: " header, trimming any supplied left case-sensitive file name prefix, e.g. with NginxSendFileFrom('/var/www'):

 # Will serve /var/www/protected_files/myfile.tar.gz
 # When passed URI /protected_files/myfile.tar.gz
 location /protected_files {
  internal;
  root /var/www;
 }

- call this method several times to register several folders


procedure SetAuthorizeBasic(const BasicRealm: RawUtf8; const OnBasicAuth: TOnHttpServerBasicAuth); overload;

Allow optional BASIC authentication for some URIs via a callback
- if OnBeforeBody returns 401, the OnBasicAuth callback will be executed to negotiate Basic authentication with the client


procedure SetAuthorizeBasic(const Basic: IBasicAuthServer); overload;

Allow optional BASIC authentication for some URIs via IBasicAuthServer
- if OnBeforeBody returns 401, Digester.OnCheckCredential will be called to negotiate Basic authentication with the client
- the supplied Digester will be owned by this instance: it could be either a TDigestAuthServerFile with its own storage, or a TDigestAuthServerMem instance expecting manual SetCredential() calls


procedure SetAuthorizeDigest(const Digest: IDigestAuthServer);

Allow optional DIGEST authentication for some URIs
- if OnBeforeBody returns 401, Digester.ServerInit and ServerAuth will be called to negotiate Digest authentication with the client
- the supplied Digester will be owned by this instance - typical use is with a TDigestAuthServerFile


procedure SetAuthorizeNone;

Remove any previous SetAuthorizeBasic/SetAuthorizeDigest registration


procedure WaitStarted(Seconds: integer; const CertificateFile: TFileName; const PrivateKeyFile: TFileName = ''; const PrivateKeyPassword: RawUtf8 = ''; const CACertificatesFile: TFileName = ''); overload;

Ensure the HTTP server thread is actually bound to the specified port
- TCrtSocket.Bind() occurs in the background in the Execute method: you should call and check this method result just after THttpServer.Create
- initial THttpServer design was to call Bind() within Create, which works fine on Delphi + Windows, but fails with a EThreadError on FPC/Linux
- raise a EHttpServer if binding failed within the specified period (if port is free, it would be almost immediate)
- calling this method is optional, but if the background thread didn't actually bind the port, the server will be stopped and unresponsive with no explicit error message, until it is terminated
- for hsoEnableTls support, you should either specify the private key and certificate here, or set TLS.PrivateKeyFile/CertificateFile fields - the benefit of this method parameters is that the certificates are loaded and checked now by calling InitializeTlsAfterBind, not at the first client connection (which may be too late)


procedure WaitStarted(Seconds: integer = 30; TLS: PNetTlsContext = nil); overload;

Ensure the HTTP server thread is actually bound to the specified port
- for hsoEnableTls support, allow to specify all server-side TLS events, including callbacks, as supported by OpenSSL
- will raise EHttpServer if the server did not start properly, e.g. could not bind the port within the supplied time


procedure WaitStartedHttps(Seconds: integer = 30; UsePreComputed: boolean = false);

Ensure the server thread is bound as self-signed HTTPS server
- wrap InitNetTlsContextSelfSignedServer() and WaitStarted() with some temporary key files, which are deleted once started
- as used e.g. by TRestHttpServer for secTLSSelfSigned


property Authorize: THttpServerRequestAuthentication read fAuthorize;

Set after a call to SetAuthDigest/SetAuthBasic


property ExecuteState: THttpServerExecuteState read GetExecuteState;

The low-level thread execution thread


property HeaderRetrieveAbortDelay: cardinal read fHeaderRetrieveAbortDelay write fHeaderRetrieveAbortDelay;

Milliseconds delay to reject a connection due to too long header retrieval
- default is 0, i.e. not checked (typical behind a reverse proxy)


property RegisterCompressGzStatic: boolean read GetRegisterCompressGzStatic write SetRegisterCompressGzStatic;

If we should search for local .gz cached file when serving static files


property ServerKeepAliveTimeOut: cardinal read fServerKeepAliveTimeOut write fServerKeepAliveTimeOut;

Time, in milliseconds, for the HTTP/1.1 connections to be kept alive
- default is 30000 ms, i.e. 30 seconds
- setting 0 here (or in KeepAliveTimeOut constructor parameter) will disable keep-alive, and fallback to HTTP.1/0 for all incoming requests (may be a good idea e.g. behind a NGINX reverse proxy)
- see THttpApiServer.SetTimeOutLimits(aIdleConnection) parameter


property Sock: TCrtSocket read fSock;

Access to the main server low-level Socket
- it's a raw TCrtSocket, which only need a socket to be bound, listening and accept incoming request
- for THttpServer inherited class, will own its own instance, then THttpServerSocket/THttpServerResp are created for every connection
- for THttpAsyncServer inherited class, redirect to TAsyncServer.fServer


property SockPort: RawUtf8 read fSockPort;

The bound TCP port, as specified to Create() constructor


property StatBanned: integer index grBanned read GetStat;

How many HTTP connections have been not accepted by hsoBan40xIP option


property StatBodyProcessed: integer index grBodyReceived read GetStat;

How many HTTP bodies have been processed


property StatHeaderClosed: integer index grClosed read GetStat;

How many HTTP connections have been closed


property StatHeaderException: integer index grException read GetStat;

How many invalid HTTP headers raised an exception


property StatHeaderProcessed: integer index grHeaderReceived read GetStat;

How many HTTP headers have been processed


property StatHeaderTimeout: integer index grTimeout read GetStat;

How many HTTP requests were rejected after HeaderRetrieveAbortDelay timeout


property StatIntercepted: integer index grIntercepted read GetStat;

How many HTTP requests were intercepted by the OnHeaderParser event handler


property StatOversizedPayloads: integer index grOversizedPayload read GetStat;

How many HTTP requests pushed more than MaximumAllowedContentLength bytes


property StatRejected: integer index grRejected read GetStat;

How many HTTP requests were rejected by the OnBeforeBody event handler


property StatUpgraded: integer index grUpgraded read GetStat;

How many HTTP connections were upgraded e.g. to WebSockets


property StatWwwAuthenticate: integer index grWwwAuthenticate read GetStat;

How many HTTP 401 "WWW-Authenticate:" responses have been returned


1.3.14. THttpServer

THttpServer = class(THttpServerSocketGeneric)

Main HTTP server Thread using the standard Sockets API (e.g. WinSock)
- bind to a port and listen to incoming requests
- assign this requests to THttpServerResp threads from a ThreadPool
- it implements a HTTP/1.1 compatible server, according to RFC 2068 specifications
- if the client is also HTTP/1.1 compatible, KeepAlive connection is handled: multiple requests will use the existing connection and thread; this is faster and uses less resources, especialy under Windows
- a Thread Pool is used internally to speed up HTTP/1.0 connections - a typical use, under Linux, is to run this class behind a NGINX frontend, configured as https reverse proxy, leaving default "proxy_http_version 1.0" and "proxy_request_buffering on" options for best performance, and setting KeepAliveTimeOut=0 in the THttpServer.Create constructor
- consider using THttpAsyncServer from mormot.net.async if a very high number of concurrent connections is expected, e.g. if using HTTP/1.0 behind a https reverse proxy is not an option
- under Windows, will trigger the firewall UAC popup at first run
- don't forget to use Free method when you are finished
- a typical HTTPS server usecase could be:

 fHttpServer := THttpServer.Create('443', nil, nil, '', 32, 30000, [hsoEnableTls]);
 fHttpServer.WaitStarted('cert.pem', 'privkey.pem', '');  // cert.pfx for SSPI
 // now certificates will be initialized and used

constructor Create(const aPort: RawUtf8; const OnStart, OnStop: TOnNotifyThread; const ProcessName: RawUtf8; ServerThreadPoolCount: integer = 32; KeepAliveTimeOut: integer = 30000; ProcessOptions: THttpServerOptions = []); override;

Create a socket-based HTTP Server, ready to be bound and listening on a port
- ServerThreadPoolCount < 0 would use a single thread to rule them all
- ServerThreadPoolCount = 0 would create one thread per connection
- ServerThreadPoolCount > 0 would leverage the thread pool, and create one thread only for kept-alive or upgraded connections


destructor Destroy; override;

Release all memory and handlers


property Banned: THttpAcceptBan read fBanned;

Set if hsoBan40xIP has been defined
- indicates e.g. how many accept() have been rejected from their IP
- you can customize its behavior once the server is started by resetting its Seconds/Max/WhiteIP properties, before any connections are made


property OnAcceptIdle: TOnPollSocketsIdle read fOnAcceptIdle write fOnAcceptIdle;

Low-level callback called every few seconds of inactive Accept()
- is called every 5 seconds by default, but could be every second if hsoBan40xIP option (i.e. the Banned property) has been set
- on Windows, requires some requests to trigger the event, because it seems that accept() has timeout only on POSIX systems


property OnHeaderParsed: TOnHttpServerHeaderParsed read fOnHeaderParsed write fOnHeaderParsed;

Low-level callback called before OnBeforeBody and allow quick execution directly from THttpServerSocket.GetRequest


property ServerConnectionActive: integer read fServerConnectionActive write fServerConnectionActive;

Will contain the current number of connections to the server


property ServerConnectionCount: integer read fServerConnectionCount write fServerConnectionCount;

Will contain the total number of connections to the server
- it's the global count since the server started


property ThreadPool: TSynThreadPoolTHttpServer read fThreadPool;

The associated thread pool
- may be nil if ServerThreadPoolCount was 0 on constructor


1.3.15. THttpPeerCacheHash

THttpPeerCacheHash = packed record

Store a hash value and its algorithm, for THttpPeerCacheMessage.Hash
- we store and compare in our implementation the algorithm in addition to the hash, to avoid any potential attack about (unlikely) hash collisions between algorithms, and allow any change of algo restrictions in the future


Algo: THashAlgo;

The algorithm used for Hash


Hash: THash512Rec;

Up to 512-bit of raw binary hash, according to Algo


1.3.16. THttpPeerCacheMessage

THttpPeerCacheMessage = packed record

One UDP request frame used during THttpPeerCache discovery
- requests and responses have the same binary layout
- some fields may be void or irrelevant, and the structure is padded with random up to 192 bytes
- over the wire, packets are encrypted and authenticated via AES-GCM-128 with an ending salted checksum for quick anti-fuzzing


BroadcastIP4: cardinal;

The IPv4 broadcast address the local network interface
- e.g. 192.168.1.255


Connections: word;

Number of background download connections currently on this server


DestIP4: cardinal;

The destination IPv4 of this frame
- contains 0 for a broadcast
- allows to filter response frames when broadcasted on POSIX


Hardware: TMacAddressKind;

The hardware model of this network interface


Hash: THttpPeerCacheHash;

Up to 512-bit of binary Hash (and algo) of the requested file content


IP4: cardinal;

The local IPv4 which sent this frame
- e.g. 192.168.1.1


Kind: THttpPeerCacheMessageKind;

The content of this binary frame


MaskIP4: cardinal;

The IPv4 network mask of the local network interface
- e.g. 255.255.255.0


Opaque: QWord;

Some internal state representation, e.g. sent back as pcfBearer


Os: TOperatingSystemVersion;

The Operating System of the Sender


Padding: array[0 .. 42] of byte;

Some random padding up to 192 bytes, used for future content revisions
- e.g. for a TEccPublicKey (ECDHE) and additional fields


RangeEnd: Int64;

The Range ending position of the file content (included)


RangeStart: Int64;

The Range offset of the requested file content


Seq: cardinal;

32-bit sequence number


Size: Int64;

The known full size of this file


Speed: cardinal;

The link speed (in Mbits per second) of the local network interface


Timestamp: cardinal;

The local UnixTimeMinimalUtc value


Uuid: TGuid;

The UUID of the Sender


1.3.17. THttpPeerCacheSettings

THttpPeerCacheSettings = class(TSynPersistent)

Define how THttpPeerCache handles its process


constructor Create; override;

Set the default settings
- i.e. Port=8099, LimitMBPerSec=10, LimitClientCount=32, RejectInstablePeersMin=4, CacheTempMaxMB=1000, CacheTempMaxMin=60, CacheTempMinBytes=CachePermMinBytes=2048, BroadcastTimeoutMS=10 HttpTimeoutMS=500 and BroadcastMaxResponses=24


property BroadcastMaxResponses: integer read fBroadcastMaxResponses write fBroadcastMaxResponses;

How many responses UDP broadcast should take into account
- default is 24


property BroadcastTimeoutMS: integer read fBroadcastTimeoutMS write fBroadcastTimeoutMS;

How many milliseconds UDP broadcast should wait for a response
- default is 10 ms which seems enough on a local network
- on Windows, this value is indicative, likely to have 15ms resolution


property CachePermMinBytes: integer read fCachePermMinBytes write fCachePermMinBytes;

Above how many bytes the peer network should be asked for a permanent file
- there is no size limitation if the file is already in the permanent cache, or if the waoNoMinimalSize option is specified by WGet()
- default is 2048 bytes, i.e. 2KB, which is just two network MTU trips


property CachePermPath: TFileName read fCachePermPath write fCachePermPath;

Location of the permanent cached files, available for remote requests
- in respect to CacheTempPath, this folder won't be purged
- the files are cached using their THttpPeerCacheHash values as filename
- if this value equals '', or pcoNoServer is defined in Options, permanent caching would be disabled


property CacheTempMaxMB: integer read fCacheTempMaxMB write fCacheTempMaxMB;

After how many MB in CacheTempPath the folder should be cleaned
- default is 1000, i.e. just below 1 GB
- THttpPeerCache.Create will also always ensure that this value won't take more than 25% of the CacheTempPath folder available space


property CacheTempMaxMin: integer read fCacheTempMaxMin write fCacheTempMaxMin;

After how many minutes files in CacheTempPath could be cleaned
- i.e. the Time-To-Live (TTL) of temporary files
- default is 60 minutes, i.e. 1 hour


property CacheTempMinBytes: integer read fCacheTempMinBytes write fCacheTempMinBytes;

Above how many bytes the peer network should be asked for a temporary file
- there is no size limitation if the file is already in the temporary cache, or if the waoNoMinimalSize option is specified by WGet()
- default is 2048 bytes, i.e. 2KB


property CacheTempPath: TFileName read fCacheTempPath write fCacheTempPath;

Location of the temporary cached files, available for remote requests
- the files are cached using their THttpPeerCacheHash values as filename
- this folder will be purged according to CacheTempMaxMB/CacheTempMaxMin
- if this value equals '', or pcoNoServer is defined in Options, temporary caching would be disabled


property HttpTimeoutMS: integer read fHttpTimeoutMS write fHttpTimeoutMS;

The socket level timeout for HTTP requests
- default to low 500 ms because should be local


property InterfaceFilter: TMacAddressFilter read fInterfaceFilter write fInterfaceFilter;

How GetMacAddress() should find the network, if InterfaceName is not set


property InterfaceName: RawUtf8 read fInterfaceName write fInterfaceName;

Local TMacAddress.Name, Address or IP to be used for UDP and TCP
- Name and Address will be searched case-insensitive
- IP could be exact or eventually a bitmask pattern (e.g. 192.168.1.255)
- if not set, will fallback to the best local makEthernet/makWifi network with broadcasting abilities
- matching TMacAddress.IP will be used with the Port property value to bind the TCP/HTTP server and broadcast the UDP discovery packets, so that only this network interface will be involved to find cache peers


property LimitClientCount: integer read fLimitClientCount write fLimitClientCount;

Can limit how many peer clients can be served content at the same time
- would prevent any overload, to avoid Denial of Service
- default is 32, which means 32 threads with the default THttpServer


property LimitMBPerSec: integer read fLimitMBPerSec write fLimitMBPerSec;

Can limit the peer bandwidth used, in data MegaBytes per second
- will be assigned to each TStreamRedirect.LimitPerSecond instance
- default is 10 MB/s of data, i.e. aroung 100-125 MBit/s on network
- you may set 0 to disable any bandwidth limitation
- you may set -1 to use the default TStreamRedirect.LimitPerSecond value


property Options: THttpPeerCacheOptions read fOptions write fOptions;

Allow to customize the process


property Port: TNetPort read fPort write fPort;

The local port used for UDP and TCP process
- value should match on all peers for proper discovery
- UDP for discovery, TCP for HTTP/HTTPS content delivery
- is 8099 by default, which is unassigned by IANA


property RejectInstablePeersMin: integer read fRejectInstablePeersMin write fRejectInstablePeersMin;

RejectInstablePeersMin will set a delay (in minutes) to ignore any peer which sent invalid UDP frames or HTTP/HTTPS requests
- should be a positive small power of two <= 128
- default is 4, for a 4 minutes time-to-live of IP banishments
- you may set 0 to disable the whole IP ban safety mechanism at UDP level
- use pcoNoBanIP option to disable the IP ban mechanism at HTTP level


1.3.18. THttpPeerCrypt

THttpPeerCrypt = class(TInterfacedObjectWithCustomCreate)

Abstract parent to THttpPeerCache for its cryptographic core


constructor Create(const aSharedSecret: RawByteString); reintroduce;

Initialize the cryptography of this peer-to-peer node instance
- warning: inherited class should also call AfterSettings once fSettings is defined


destructor Destroy; override;

Finalize this class instance


1.3.19. EHttpPeerCache

EHttpPeerCache = class(ESynException)

Exception class raised on THttpPeerCache issues


1.3.20. THttpPeerCacheThread

THttpPeerCacheThread = class(TUdpServerThread)

Background UDP server thread, associated to a THttpPeerCache instance


constructor Create(Owner: THttpPeerCache); reintroduce;

Initialize the background UDP server thread


destructor Destroy; override;

Finalize this instance


1.3.21. THttpPeerCache

THttpPeerCache = class(THttpPeerCrypt)

Implement a local peer-to-peer download cache via UDP and TCP
- UDP broadcasting is used for local peers discovery
- TCP is bound to a local THttpServer/THttpAsyncServer content delivery
- will maintain its own local folders of cached files, stored by hash


constructor Create(aSettings: THttpPeerCacheSettings; const aSharedSecret: RawByteString; aHttpServerClass: THttpServerSocketGenericClass = nil; aHttpServerThreadCount: integer = 2; aLogClass: TSynLogClass = nil; const aUuid: RawUtf8 = ''); reintroduce;

Initialize this peer-to-peer cache instance
- any supplied aSettings should be owned by the caller (e.g from a main settings class instance)
- aSharedSecret is used to cipher and authenticate each UDP frame between all peer nodes, and also generate HTTP authentication bearers
- if aSettings = nil, default values will be used by this instance
- you can supply THttpAsyncServer class to replace default THttpServer
- may raise some exceptions if the HTTP server cannot be started


destructor Destroy; override;

Finalize this peer-to-peer cache instance


function OnBeforeBody(var aUrl, aMethod, aInHeaders, aInContentType, aRemoteIP, aBearerToken: RawUtf8; aContentLength: Int64; aFlags: THttpServerRequestFlags): cardinal; virtual;

Method called by the HttpServer before any request is processed
- will reject anything but a GET with a proper bearer, from the right IP


function OnDownload(Sender: THttpClientSocket; var Params: THttpClientSocketWGet; const Url: RawUtf8; ExpectedFullSize: Int64; OutStream: TStreamRedirect): integer; virtual;

IWGetAlternate main processing method, as used by THttpClientSocketWGet
- will transfer Sender.Server/Port/RangeStart/RangeEnd into OutStream
- OutStream.LimitPerSecond will be overriden during the call
- could return 0 to fallback to a regular GET (e.g. not cached)


function OnDownloading(const Params: THttpClientSocketWGet; const Partial: TFileName; ExpectedFullSize: Int64): THttpPartialID;

IWGetAlternate main processing method, as used by THttpClientSocketWGet
- make this .part file available as pcfResponsePartial
- returns PartialID > 0 sequence


function OnRequest(Ctxt: THttpServerRequestAbstract): cardinal; virtual;

Method called by the HttpServer to process a request
- statically serve a local file from decoded bearer hash


function Ping: THttpPeerCacheMessageDynArray;

Broadcast a pcfPing on the network interface and return the responses


procedure OnDowloaded(var Params: THttpClientSocketWGet; const Partial: TFileName; PartialID: integer); virtual;

IWGetAlternate main processing method, as used by THttpClientSocketWGet
- if a file has been downloaded from the main repository, this method should be called to copy the content into this instance files cache


procedure OnDownloadFailed(const Params: THttpClientSocketWGet);

IWGetAlternate main processing method, as used by THttpClientSocketWGet
- OnDownload() may have returned corrupted data: local cache file is likely to be deleted, for safety


procedure OnDownloadingFailed(ID: THttpPartialID);

IWGetAlternate main processing method, as used by THttpClientSocketWGet notify the alternate download implementation that OnDownloading() failed
- e.g. THttpPeerCache is likely to abort publishing this partial file


procedure OnIdle(tix64: Int64);

Is called on a regular basis for background regular process
- is called from THttpPeerCacheThread.OnIdle
- e.g. to implement optional CacheTempMaxMin disk space release, actually reading and purging the CacheTempPath folder every minute
- could call Instable.DoRotate every minute to refresh IP banishments


property HttpServer: THttpServerGeneric read fHttpServer;

The associated HTTP/HTTPS server delivering cached context


property Instable: THttpAcceptBan read fInstable;

The current state of banned IP from incorrect UDP/HTTP requests
- follow RejectInstablePeersMin settings


property Mac: TMacAddress read fMac;

The network interface used for UDP and TCP process


property NetworkBroadcast: RawUtf8 read fMac.Broadcast;

The IP used for UDP and TCP process broadcast


property NetworkInterface: RawUtf8 read fMac.Name;

Which network interface is used for UDP and TCP process


property Settings: THttpPeerCacheSettings read fSettings;

Define how this instance handles its process


property Uuid: TGuid read fUuid write fUuid;

The UUID used to identify this node
- is filled by GetComputerUuid() from SMBios by default
- could be customized if necessary after Create()


1.3.22. THttpPeerCacheProcess

THttpPeerCacheProcess = class(TSynPersistent)

One THttpPeerCache.OnDownload instance


1.3.23. THttpApiServer

THttpApiServer = class(THttpServerGeneric)

HTTP server using fast http.sys kernel-mode server
- The HTTP Server API enables applications to communicate over HTTP without using Microsoft Internet Information Server (IIS). Applications can register to receive HTTP requests for particular URLs, receive HTTP requests, and send HTTP responses. The HTTP Server API includes TLS support so that applications can exchange data over secure HTTP connections without IIS. It is also designed to work with I/O completion ports.
- The HTTP Server API is supported on Windows Server 2003 operating systems and on Windows XP with Service Pack 2 (SP2). Be aware that Microsoft IIS 5 running on Windows XP with SP2 is not able to share port 80 with other HTTP applications running simultaneously.


constructor Create(QueueName: SynUnicode = ''; const OnStart: TOnNotifyThread = nil; const OnStop: TOnNotifyThread = nil; const ProcessName: RawUtf8 = ''; ProcessOptions: THttpServerOptions = []); reintroduce;

Initialize the HTTP Service
- will raise an exception if http.sys is not available e.g. before Windows XP SP2) or if the request queue creation failed
- if you override this contructor, put the AddUrl() methods within, and you can set CreateSuspended to FALSE
- if you will call AddUrl() methods later, set CreateSuspended to TRUE, then call explicitly the Resume method, after all AddUrl() calls, in order to start the server


constructor CreateClone(From: THttpApiServer); virtual;

Create a HTTP/1.1 processing clone from the main thread
- do not use directly - is called during thread pool creation


destructor Destroy; override;

Release all associated memory and handles


function AddUrl(const aRoot, aPort: RawUtf8; Https: boolean = false; const aDomainName: RawUtf8 = '*'; aRegisterUri: boolean = false; aContext: Int64 = 0): integer;

Register the URLs to Listen On
- e.g. AddUrl('root','888')
- aDomainName could be either a fully qualified case-insensitive domain name, an IPv4 or IPv6 literal string, or a wildcard ('+' will bound to all domain names for the specified port, '*' will accept the request when no other listening hostnames match the request for that port)
- return 0 (NO_ERROR) on success, an error code if failed: under Vista and Seven, you could have ERROR_ACCESS_DENIED if the process is not running with enough rights (by default, UAC requires administrator rights for adding an URL to http.sys registration list) - solution is to call the THttpApiServer.AddUrlAuthorize class method during program setup
- if this method is not used within an overridden constructor, default Create must have be called with CreateSuspended = TRUE and then call the Resume method after all Url have been added
- if aRegisterUri is TRUE, the URI will be registered (need adminitrator rights) - default is FALSE, as defined by Windows security policy


class function AddUrlAuthorize(const aRoot, aPort: RawUtf8; Https: boolean = false; const aDomainName: RawUtf8 = '*'; OnlyDelete: boolean = false): string;

Will authorize a specified URL prefix
- will allow to call AddUrl() later for any user on the computer
- if aRoot is left '', it will authorize any root for this port
- must be called with Administrator rights: this class function is to be used in a Setup program for instance, especially under Vista or Seven, to reserve the Url for the server
- add a new record to the http.sys URL reservation store
- return '' on success, an error message otherwise
- will first delete any matching rule for this URL prefix
- if OnlyDelete is true, will delete but won't add the new authorization; in this case, any error message at deletion will be returned


function HasApi2: boolean;

Can be used to check if the HTTP API 2.0 is available


function RemoveUrl(const aRoot, aPort: RawUtf8; Https: boolean = false; const aDomainName: RawUtf8 = '*'): integer;

Un-register the URLs to Listen On
- this method expect the same parameters as specified to AddUrl()
- return 0 (NO_ERROR) on success, an error code if failed (e.g.
-1 if the corresponding parameters do not match any previous AddUrl)


procedure Clone(ChildThreadCount: integer);

Will clone this thread into multiple other threads
- could speed up the process on multi-core CPU
- will work only if the OnProcess property was set (this is the case e.g. in TRestHttpServer.Create() constructor)
- maximum value is 256 - higher should not be worth it


procedure LogStart(const aLogFolder: TFileName; aType: THttpApiLoggingType = hltW3C; const aSoftwareName: TFileName = ''; aRolloverType: THttpApiLoggingRollOver = hlrDaily; aRolloverSize: cardinal = 0; aLogFields: THttpApiLogFields = [hlfDate..hlfSubStatus]; aFlags: THttpApiLoggingFlags = [hlfUseUtf8Conversion]);

Enable HTTP API 2.0 logging
- will raise an EHttpApiServer exception if the old HTTP API 1.x is used so you should better test the availability of the method first:

 if aServer.HasApi2 then
   LogStart(....);

- this method won't do anything on the cloned instances, but the main instance logging state will be replicated to all cloned instances
- you can select the output folder and the expected logging layout
- aSoftwareName will set the optional W3C-only software name string
- aRolloverSize will be used only when aRolloverType is hlrSize


procedure LogStop;

Disable HTTP API 2.0 logging
- this method won't do anything on the cloned instances, but the main instance logging state will be replicated to all cloned instances


procedure RegisterCompress(aFunction: THttpSocketCompress; aCompressMinSize: integer = 1024; aPriority: integer = 10); override;

Will register a compression algorithm
- overridden method which will handle any cloned instances


procedure SetAuthenticationSchemes(schemes: THttpApiRequestAuthentications; const DomainName: SynUnicode = ''; const Realm: SynUnicode = '');

Enable HTTP API 2.0 server-side authentication
- once enabled, the client sends an unauthenticated request: it is up to the server application to generate the initial 401 challenge with proper WWW-Authenticate headers; any further authentication steps will be perform in kernel mode, until the authentication handshake is finalized; later on, the application can check the AuthenticationStatus property of THttpServerRequest and its associated AuthenticatedUser value see https://msdn.microsoft.com/en-us/library/windows/desktop/aa364452
- will raise an EHttpApiServer exception if the old HTTP API 1.x is used so you should better test the availability of the method first:

 if aServer.HasApi2 then
   SetAuthenticationSchemes(....);

- this method will work on the current group, for all instances
- see HTTPAPI_AUTH_ENABLE_ALL constant to set all available schemes
- optional Realm parameters can be used when haBasic scheme is defined
- optional DomainName and Realm parameters can be used for haDigest


procedure SetTimeOutLimits(aEntityBody, aDrainEntityBody, aRequestQueue, aIdleConnection, aHeaderWait, aMinSendRate: cardinal);

Enable HTTP API 2.0 advanced timeout settings
- all those settings are set for the current URL group
- will raise an EHttpApiServer exception if the old HTTP API 1.x is used so you should better test the availability of the method first:

 if aServer.HasApi2 then
   SetTimeOutLimits(....);

- aEntityBody is the time, in seconds, allowed for the request entity body to arrive - default value is 2 minutes
- aDrainEntityBody is the time, in seconds, allowed for the HTTP Server API to drain the entity body on a Keep-Alive connection - default value is 2 minutes
- aRequestQueue is the time, in seconds, allowed for the request to remain in the request queue before the application picks it up - default value is 2 minutes
- aIdleConnection is the time, in seconds, allowed for an idle connection; is similar to THttpServer.ServerKeepAliveTimeOut - default value is 2 minutes
- aHeaderWait is the time, in seconds, allowed for the HTTP Server API to parse the request header - default value is 2 minutes
- aMinSendRate is the minimum send rate, in bytes-per-second, for the response - default value is 150 bytes-per-second
- any value set to 0 will set the HTTP Server API default value


property AuthenticationSchemes: THttpApiRequestAuthentications read fAuthenticationSchemes;

Read-only access to HTTP API 2.0 server-side enabled authentication schemes


property Cloned: boolean read GetCloned;

TRUE if this instance is in fact a cloned instance for the thread pool


property Clones: THttpApiServers read fClones;

Access to the internal THttpApiServer list cloned by this main instance
- as created by Clone() method


property Logging: boolean read GetLogging;

Read-only access to check if the HTTP API 2.0 logging is enabled
- use LogStart/LogStop methods to change this property value


property LoggingServiceName: RawUtf8 read fLoggingServiceName write SetLoggingServiceName;

The current HTTP API 2.0 logging Service name
- should be UTF-8 encoded, if LogStart(aFlags=[hlfUseUtf8Conversion])
- this value is dedicated to one instance, so the main instance won't propagate the change to all cloned instances


property MaxBandwidth: cardinal read GetMaxBandwidth write SetMaxBandwidth;

The maximum allowed bandwidth rate in bytes per second (via HTTP API 2.0)
- Setting this value to 0 allows an unlimited bandwidth
- by default Windows not limit bandwidth (actually limited to 4 Gbit/sec).
- will return 0 if the system does not support HTTP API 2.0 (i.e. under Windows XP or Server 2003)


property MaxConnections: cardinal read GetMaxConnections write SetMaxConnections;

The maximum number of HTTP connections allowed (via HTTP API 2.0)
- Setting this value to 0 allows an unlimited number of connections
- by default Windows does not limit number of allowed connections
- will return 0 if the system does not support HTTP API 2.0 (i.e. under Windows XP or Server 2003)


property ReceiveBufferSize: cardinal read fReceiveBufferSize write SetReceiveBufferSize;

How many bytes are retrieved in a single call to ReceiveRequestEntityBody
- set by default to 1048576, i.e. 1 MB - practical limit is around 20 MB
- you may customize this value if you encounter HTTP error HTTP_NOTACCEPTABLE (406) from client, corresponding to an ERROR_NO_SYSTEM_RESOURCES (1450) exception on server side, when uploading huge data content


property RegisteredUrl: SynUnicode read GetRegisteredUrl;

Return the list of registered URL on this server instance


property ServerSessionID: HTTP_SERVER_SESSION_ID read fServerSessionID;

Read-only access to the low-level HTTP API 2.0 Session ID


property UrlGroupID: HTTP_URL_GROUP_ID read fUrlGroupID;

Read-only access to the low-level HTTP API 2.0 URI Group ID


1.3.24. THttpApiWebSocketConnection

THttpApiWebSocketConnection = object(TObject)

Structure representing a single WebSocket connection


procedure Close(aStatus: WEB_SOCKET_CLOSE_STATUS; aBuffer: pointer; aBufferSize: ULONG);

Close connection


procedure Send(aBufferType: WEB_SOCKET_BUFFER_TYPE; aBuffer: pointer; aBufferSize: ULONG);

Send data to client


property Index: integer read fIndex;

Index of connection in protocol's connection list


property PrivateData: pointer read fPrivateData write fPrivateData;

Custom user data


property Protocol: THttpApiWebSocketServerProtocol read fProtocol;

Protocol of connection


property State: TWebSocketState read fState;

Access to the current state of this connection


1.3.25. THttpApiWebSocketServerProtocol

THttpApiWebSocketServerProtocol = class(TObject)

Protocol Handler of websocket endpoints events
- maintains a list of all WebSockets clients for a given protocol


constructor Create(const aName: RawUtf8; aManualFragmentManagement: boolean; aServer: THttpApiWebSocketServer; const aOnAccept: TOnHttpApiWebSocketServerAcceptEvent; const aOnMessage: TOnHttpApiWebSocketServerMessageEvent; const aOnConnect: TOnHttpApiWebSocketServerConnectEvent; const aOnDisconnect: TOnHttpApiWebSocketServerDisconnectEvent; const aOnFragment: TOnHttpApiWebSocketServerMessageEvent = nil);

Initialize the WebSockets process
- if aManualFragmentManagement is true, onMessage will appear only for whole received messages, otherwise OnFragment handler must be passed (for video broadcast, for example)


destructor Destroy; override;

Finalize the process


function Broadcast(aBufferType: ULONG; aBuffer: pointer; aBufferSize: ULONG): boolean;

Send message to all connections of this protocol


function Close(index: integer; aStatus: WEB_SOCKET_CLOSE_STATUS; aBuffer: pointer; aBufferSize: ULONG): boolean;

Close WebSocket connection identified by its index


function Send(index: integer; aBufferType: ULONG; aBuffer: pointer; aBufferSize: ULONG): boolean;

Send message to the WebSocket connection identified by its index


property Index: integer read fIndex;

Identify the endpoint instance


property ManualFragmentManagement: boolean read fManualFragmentManagement;

OnFragment event will be called for each fragment


property Name: RawUtf8 read fName;

Text identifier


property OnAccept: TOnHttpApiWebSocketServerAcceptEvent read fOnAccept;

Event triggerred when a WebSockets client is initiated


property OnConnect: TOnHttpApiWebSocketServerConnectEvent read fOnConnect;

Event triggerred when a WebSockets client is connected


property OnDisconnect: TOnHttpApiWebSocketServerDisconnectEvent read fOnDisconnect;

Event triggerred when a WebSockets client is gracefully disconnected


property OnFragment: TOnHttpApiWebSocketServerMessageEvent read fOnFragment;

Event triggerred when a non complete frame is received
- required if ManualFragmentManagement is true


property OnMessage: TOnHttpApiWebSocketServerMessageEvent read fOnMessage;

Event triggerred when a WebSockets message is received


1.3.26. THttpApiWebSocketServer

THttpApiWebSocketServer = class(THttpApiServer)

HTTP & WebSocket server using fast http.sys kernel-mode server
- can be used like simple THttpApiServer
- when AddUrlWebSocket is called WebSocket support are added in this case WebSocket will receiving the frames in asynchronous


constructor Create(aSocketThreadsCount: integer = 1; aPingTimeout: integer = 0; const QueueName: SynUnicode = ''; const aOnWSThreadStart: TOnNotifyThread = nil; const aOnWSThreadTerminate: TOnNotifyThread = nil; ProcessOptions: THttpServerOptions = []); reintroduce;

Initialize the HTTPAPI based Server with WebSocket support
- will raise an exception if http.sys or websocket.dll is not available (e.g. before Windows 8) or if the request queue creation failed
- for aPingTimeout explanation see PingTimeout property documentation


constructor CreateClone(From: THttpApiServer); override;

Create a WebSockets processing clone from the main thread
- do not use directly - is called during thread pool creation


function AddUrlWebSocket(const aRoot, aPort: RawUtf8; Https: boolean = false; const aDomainName: RawUtf8 = '*'; aRegisterUri: boolean = false): integer;

Register the URLs to Listen on using WebSocket
- aProtocols is an array of a recond with callbacks, server call during WebSocket activity


function Request(Ctxt: THttpServerRequestAbstract): cardinal; override;

Handle the HTTP request


procedure RegisterProtocol(const aName: RawUtf8; aManualFragmentManagement: boolean; const aOnAccept: TOnHttpApiWebSocketServerAcceptEvent; const aOnMessage: TOnHttpApiWebSocketServerMessageEvent; const aOnConnect: TOnHttpApiWebSocketServerConnectEvent; const aOnDisconnect: TOnHttpApiWebSocketServerDisconnectEvent; const aOnFragment: TOnHttpApiWebSocketServerMessageEvent = nil);

Prepare the process for a given THttpApiWebSocketServerProtocol


procedure SendServiceMessage;

Send a "service" message to a WebSocketServer to wake up a WebSocket thread
- can be called from any thread
- when a webSocket thread receives such a message it will call onServiceMessage in the thread context


property OnServiceMessage: TThreadMethod read fOnServiceMessage write fOnServiceMessage;

Event called when a service message is raised


property OnWSThreadStart: TOnNotifyThread read FOnWSThreadStart write SetOnWSThreadStart;

Event called when the processing thread starts


property OnWSThreadTerminate: TOnNotifyThread read FOnWSThreadTerminate write SetOnWSThreadTerminate;

Event called when the processing thread termintes


property PingTimeout: integer read fPingTimeout;

Ping timeout in seconds. 0 mean no ping.
- if connection not receive messages longer than this timeout TSynWebSocketGuard will send ping frame
- if connection not receive any messages longer than double of this timeout it will be closed


property Protocols[index: integer]: THttpApiWebSocketServerProtocol read GetProtocol;

Access to the associated endpoints


property ProtocolsCount: integer read getProtocolsCount;

Access to the associated endpoints count


1.3.27. TSynThreadPoolHttpApiWebSocketServer

TSynThreadPoolHttpApiWebSocketServer = class(TSynThreadPool)

A Thread Pool, used for fast handling of WebSocket requests


constructor Create(Server: THttpApiWebSocketServer; NumberOfThreads: integer = 1); reintroduce;

Initialize the thread pool


1.3.28. TSynWebSocketGuard

TSynWebSocketGuard = class(TThread)

Thread for closing deprecated WebSocket connections
- i.e. which have not responsed after PingTimeout interval


constructor Create(Server: THttpApiWebSocketServer); reintroduce;

Initialize the thread


1.4. Types implemented in the mormot.net.server unit

1.4.1. PUdpFrame

PUdpFrame = ^TUdpFrame;

Pointer to a memory buffer of the maximum size of UDP frame


1.4.2. THttpPeerCacheMessageKind

THttpPeerCacheMessageKind = ( pcfPing, pcfPong, pcfRequest, pcfResponseNone, pcfResponseOverloaded, pcfResponsePartial, pcfResponseFull, pcfBearer );

The content of a binary THttpPeerCacheMessage
- could eventually be extended in the future for frame versioning


1.4.3. THttpPeerCacheOption

THttpPeerCacheOption = ( pcoCacheTempSubFolders, pcoUseFirstResponse, pcoTryLastPeer, pcoBroadcastNotAlone, pcoNoServer, pcoNoBanIP, pcoSelfSignedHttps, pcoVerboseLog );

Each THttpPeerCacheSettings.Options item
- pcoCacheTempSubFolders will create 16 sub-folders (from first 0-9/a-z hash nibble) within CacheTempPath to reduce filesystem fragmentation
- pcoUseFirstResponse will accept the first positive response, and don't wait for the BroadcastTimeoutMS delay for all responses to be received
- pcoTryLastPeer will first check the latest peer with HTTP/TCP before making any broadcast - to be used if the files are likely to come in batch; can be forced by TWGetAlternateOptions from a given WGet() call
- pcoBroadcastNotAlone will disable broadcasting for up to one second if no response at all was received within BroadcastTimeoutMS delay
- pcoNoServer disable the local UDP/HTTP servers and acts as a pure client
- pcoNoBanIP disable the 4 seconds IP banishment mechanism at HTTP level; set RejectInstablePeersMin = 0 to disable banishment at UDP level
- pcoSelfSignedHttps enables HTTPS communication with a self-signed server (warning: this option should be set on all peers, clients and servers)
- pcoVerboseLog will log all details, e.g. raw UDP frames


1.4.4. THttpPeerCacheOptions

THttpPeerCacheOptions = set of THttpPeerCacheOption;

THttpPeerCacheSettings.Options values


1.4.5. THttpServerExecuteState

THttpServerExecuteState = ( esNotStarted, esBinding, esRunning, esFinished );

THttpServerSocketGeneric current state


1.4.6. THttpServerOption

THttpServerOption = ( hsoHeadersUnfiltered, hsoHeadersInterning, hsoNoXPoweredHeader, hsoNoStats, hsoCreateSuspended, hsoLogVerbose, hsoIncludeDateHeader, hsoEnableTls, hsoBan40xIP, hsoThreadCpuAffinity, hsoThreadSocketAffinity, hsoReusePort, hsoThreadSmooting, hsoEnablePipelining, hsoEnableLogging, hsoTelemetryCsv, hsoTelemetryJson );

Available HTTP server options
- some THttpServerGeneric classes may have only partial support of them
- hsoHeadersUnfiltered will store all headers, not only relevant (i.e. include raw Content-Length, Content-Type and Content-Encoding entries)
- hsoHeadersInterning triggers TRawUtf8Interning to reduce memory usage
- hsoNoStats will disable low-level statistic counters
- hsoNoXPoweredHeader excludes 'X-Powered-By: mORMot 2 synopse.info' header
- hsoCreateSuspended won't start the server thread immediately
- hsoLogVerbose could be used to debug a server in production
- hsoIncludeDateHeader will let all answers include a Date: ... HTTP header
- hsoEnableTls enables TLS support for THttpServer socket server, using Windows SChannel API or OpenSSL - call WaitStarted() to set the certificates
- hsoBan40xIP 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
- either hsoThreadCpuAffinity or hsoThreadSocketAffinity could be set: to force thread affinity to one CPU logic core, or CPU HW socket; see TNotifiedThread corresponding methods - not available on http.sys
- hsoReusePort will set SO_REUSEPORT on POSIX, allowing to bind several THttpServerGeneric on the same port, either within the same process, or as separated processes (e.g. to set process affinity to one CPU HW socket)
- hsoThreadSmooting will change the TAsyncConnections.ThreadPollingWakeup() algorithm to focus the process on the first threads of the pool - by design, this will disable both hsoThreadCpuAffinity and hsoThreadSocketAffinity
- hsoEnablePipelining enable HTTP pipelining (unsafe) on THttpAsyncServer
- hsoEnableLogging enable an associated THttpServerGeneric.Logger instance
- hsoTelemetryCsv and hsoTelemetryJson will enable CSV or JSON consolidated per-minute metrics logging via an associated THttpServerGeneric.Analyzer


1.4.7. THttpServerOptions

THttpServerOptions = set of THttpServerOption;

How a THttpServerGeneric class is expected to process incoming requests


1.4.8. THttpServerRequestClass

THttpServerRequestClass = class of THttpServerRequest;

Meta-class of HTTP server requests instances


1.4.9. THttpServerRespClass

THttpServerRespClass = class of THttpServerResp;

Metaclass of HTTP response Thread


1.4.10. THttpServerSocketClass

THttpServerSocketClass = class of THttpServerSocket;

Meta-class of the THttpServerSocket process
- used to override THttpServerSocket.GetRequest for instance


1.4.11. THttpServerSocketGenericClass

THttpServerSocketGenericClass = class of THttpServerSocketGeneric;

Meta-class of our THttpServerSocketGeneric classes
- typically implemented by THttpServer, TWebSocketServer, TWebSocketServerRest or THttpAsyncServer classes


1.4.12. THttpServerSocketGetRequestResult

THttpServerSocketGetRequestResult = ( grClosed, grException, grOversizedPayload, grRejected, grIntercepted, grTimeout, grHeaderReceived, grBodyReceived, grWwwAuthenticate, grUpgraded, grBanned );

Results of THttpServerSocket.GetRequest virtual method
- grClosed is returned if the socket was disconnected/closed by the client
- grException is returned if any exception occurred during the process
- grOversizedPayload is returned when MaximumAllowedContentLength is reached
- grRejected on invalid input, or when OnBeforeBody returned not 200
- grIntercepted is returned e.g. from OnHeaderParsed as valid result
- grTimeout is returned when HeaderRetrieveAbortDelay is reached
- grHeaderReceived is returned for GetRequest({withbody=}false)
- grBodyReceived is returned for GetRequest({withbody=}true)
- grWwwAuthenticate is returned if GetRequest() did send a 401 response
- grUpgraded indicates that this connection was upgraded e.g. as WebSockets
- grBanned is triggered by the hsoBan40xIP option


1.4.13. TMacAddressFilter

TMacAddressFilter = set of ( mafEthernetOnly, mafLocalOnly, mafRequireBroadcast, mafIgnoreGateway, mafIgnoreKind, mafIgnoreSpeed);

Define how GetMacAddress() makes its sorting choices
- used e.g. for THttpPeerCacheSettings.InterfaceFilter property
- mafEthernetOnly will only select TMacAddress.Kind = makEthernet
- mafLocalOnly will only select makEthernet or makWifi adapters
- mafRequireBroadcast won't return any TMacAddress with Broadcast = ''
- mafIgnoreGateway won't put the TMacAddress.Gateway <> '' first
- mafIgnoreKind and mafIgnoreSpeed will ignore Kind or Speed properties


1.4.14. TOnHttpApiWebSocketServerAcceptEvent

TOnHttpApiWebSocketServerAcceptEvent = function(Ctxt: THttpServerRequest; var Conn: THttpApiWebSocketConnection): boolean of object;

Event handler on THttpApiWebSocketServerProtocol Accepted connection


1.4.15. TOnHttpApiWebSocketServerConnectEvent

TOnHttpApiWebSocketServerConnectEvent = procedure( var Conn: THttpApiWebSocketConnection) of object;

Event handler on THttpApiWebSocketServerProtocol connection


1.4.16. TOnHttpApiWebSocketServerDisconnectEvent

TOnHttpApiWebSocketServerDisconnectEvent = procedure(var Conn: THttpApiWebSocketConnection; aStatus: WEB_SOCKET_CLOSE_STATUS; aBuffer: pointer; aBufferSize: ULONG) of object;

Event handler on THttpApiWebSocketServerProtocol disconnection


1.4.17. TOnHttpApiWebSocketServerMessageEvent

TOnHttpApiWebSocketServerMessageEvent = procedure(var Conn: THttpApiWebSocketConnection; aBufferType: WEB_SOCKET_BUFFER_TYPE; aBuffer: pointer; aBufferSize: ULONG) of object;

Event handler on THttpApiWebSocketServerProtocol Message received


1.4.18. TOnHttpServerBasicAuth

TOnHttpServerBasicAuth = function(Sender: TObject; const aUser: RawUtf8; const aPassword: SpiUtf8): boolean of object;

Callback used by THttpServerSocketGeneric.SetAuthorizeBasic
- should return true if supplied aUser/aPassword pair is valid


1.4.19. TOnHttpServerHeaderParsed

TOnHttpServerHeaderParsed = function( ClientSock: THttpServerSocket): THttpServerSocketGetRequestResult of object;

Called from THttpServerSocket.GetRequest before OnBeforeBody
- this THttpServer-specific callback allow quick and dirty action on the raw socket, to bypass the whole THttpServer.Process high-level action
- should return grRejected/grIntercepted if the action has been handled as error or success, and response has been sent directly via ClientSock.SockSend/SockSendFlush (as HTTP/1.0) by this handler
- should return grHeaderReceived to continue as usual with THttpServer.Process


1.4.20. TOnHttpServerRequestAsyncResponse

TOnHttpServerRequestAsyncResponse = procedure(Sender: THttpServerRequestAbstract; RespStatus: integer = HTTP_SUCCESS) of object;

Event signature for THttpServerRequest.AsyncResponse callback


1.4.21. TUdpFrame

TUdpFrame = array[word] of byte;

Work memory buffer of the maximum size of UDP frame (64KB)


1.4.22. TUriRouterMethod

TUriRouterMethod = ( urmGet, urmPost, urmPut, urmDelete, urmOptions, urmHead );

One HTTP method supported by TUriRouter
- only supports RESTful GET/POST/PUT/DELETE/OPTIONS/HEAD by default
- each method would have its dedicated TUriTree parser in TUriRouter


1.4.23. TUriRouterMethods

TUriRouterMethods = set of TUriRouterMethod;

The HTTP methods supported by TUriRouter


1.4.24. TUriRouterTree

TUriRouterTree = array[urmGet .. high(TUriRouterMethod)] of TUriTree;

Store per-method URI multiplexing Radix Tree in TUriRouter
- each HTTP method would have its dedicated TUriTree parser in TUriRouter


1.4.25. TWebSocketState

TWebSocketState = ( wsConnecting, wsOpen, wsClosing, wsClosedByClient, wsClosedByServer, wsClosedByGuard, wsClosedByShutdown );

Current state of a THttpApiWebSocketConnection


1.5. Constants implemented in the mormot.net.server unit

1.5.1. HTTP_10_FLAGS

HTTP_10_FLAGS: array[boolean] of THttpServerRequestFlags = ( [], [hsrHttp10]);

Used to compute the request ConnectionFlags from HTTP/1.0 command


1.5.2. HTTP_TLS_FLAGS

HTTP_TLS_FLAGS: array[boolean] of THttpServerRequestFlags = ( [], [hsrHttps, hsrSecured]);

Used to compute the request ConnectionFlags from the socket TLS state


1.5.3. HTTP_UPG_FLAGS

HTTP_UPG_FLAGS: array[boolean] of THttpServerRequestFlags = ( [], [hsrConnectionUpgrade]);

Used to compute the request ConnectionFlags from connection: upgrade header


1.5.4. THREADPOOL_BIGBODYSIZE

THREADPOOL_BIGBODYSIZE = 16 * 1024 * 1024;

If HTTP body length is bigger than 16 MB, creates a dedicated THttpServerResp
- is the default value to TSynThreadPoolTHttpServer.BigBodySize


1.5.5. THREADPOOL_MAXWORKTHREADS

THREADPOOL_MAXWORKTHREADS = 512;

Kept-alive or big HTTP requests will create a dedicated THttpServerResp
- each thread reserves 2 MB of memory so it may break the server
- keep the value to a decent number, to let resources be constrained up to 1GB
- is the default value to TSynThreadPoolTHttpServer.MaxBodyThreadCount


1.5.6. UDP_SHUTDOWN

UDP_SHUTDOWN: RawUtf8 = 'shutdown';

The UDP frame content as sent by TUdpServerThread.Destroy


1.5.7. URIROUTERMETHOD

URIROUTERMETHOD: array[TUriRouterMethod] of RawUtf8 = ( 'GET', 'POST', 'PUT', 'DELETE', 'OPTIONS', 'HEAD');

Convert TUriRouterMethod into its standard HTTP text
- see UriMethod() function for the reverse conversion


1.6. Functions or procedures implemented in the mormot.net.server unit

Functions or proceduresDescription
FavIconBinaryUsed by THttpServerGeneric.SetFavIcon to return a nice /favicon.ico
GetMainMacAddressGet a network interface from its TMacAddress main fields
GetMainMacAddressPickup the most suitable network according to some preferences
InitNetTlsContextSelfSignedServerInitialize a server-side TLS structure with a self-signed algorithm
IsValidUriRouteCheck if the supplied text contains only valid characters for a root URI
PrivKeyCertPfxSome pre-computed CryptCertOpenSsl[caaRS256].New key for Windows
UriMethodUrmGet urmPost urmPut urmDelete urmOptions urmHead quickly recognize most HTTP text methods into a TUriRouterMethod enumeration

1.6.1. FavIconBinary

function FavIconBinary: RawByteString;

Used by THttpServerGeneric.SetFavIcon to return a nice /favicon.ico


1.6.2. GetMainMacAddress

function GetMainMacAddress(out Mac: TMacAddress; Filter: TMacAddressFilter = []): boolean; overload;

Pickup the most suitable network according to some preferences
- will sort GetMacAddresses() results according to its Kind and Speed to select the most suitable local interface e.g. for THttpPeerCache


1.6.3. GetMainMacAddress

function GetMainMacAddress(out Mac: TMacAddress; const InterfaceNameAddressOrIP: RawUtf8; UpAndDown: boolean = false): boolean; overload;

Get a network interface from its TMacAddress main fields
- search is case insensitive for TMacAddress.Name and Address fields or as exact IP, and eventually as IP bitmask pattern (e.g. 192.168.1.255)


1.6.4. InitNetTlsContextSelfSignedServer

procedure InitNetTlsContextSelfSignedServer(var TLS: TNetTlsContext; Algo: TCryptAsymAlgo = caaRS256; UsePreComputed: boolean = false);

Initialize a server-side TLS structure with a self-signed algorithm
- as used e.g. by THttpServerSocketGeneric.WaitStartedHttps
- if OpenSSL is available and UsePreComputed is false, will generate a temporary pair of key files via Generate(CU_TLS_SERVER, '127.0.0.1', nil, 3650) with a random password
- if UsePreComputed=true or on pure SChannel, will use the PrivKeyCertPfx pre-computed constant
- you should eventually call DeleteFile(Utf8ToString(TLS.CertificateFile)) and DeleteFile(Utf8ToString(TLS.PrivateKeyFile)) to delete the two temp files


1.6.5. IsValidUriRoute

function IsValidUriRoute(p: PUtf8Char): boolean;

Check if the supplied text contains only valid characters for a root URI
- excluding the parameters, i.e. rejecting the ? and % characters
- but allowing <param> place holders as recognized by TUriRouter


1.6.6. PrivKeyCertPfx

function PrivKeyCertPfx: RawByteString;

Some pre-computed CryptCertOpenSsl[caaRS256].New key for Windows
- the associated password is 'pass'
- as used e.g. by THttpServerSocketGeneric.WaitStartedHttps


1.6.7. UriMethod

function UriMethod(const Text: RawUtf8; out Method: TUriRouterMethod): boolean;

UrmGet urmPost urmPut urmDelete urmOptions urmHead quickly recognize most HTTP text methods into a TUriRouterMethod enumeration
- may replace cascaded IsGet() IsPut() IsPost() IsDelete() function calls
- see URIROUTERMETHOD[] constant for the reverse conversion