What’s good about https.sys?
Kernel-mode request queuing
Requests cause less overhead in context switching, because the kernel forwards
requests directly to the correct worker process. If no worker process is
available to accept a request, the kernel-mode request queue holds the request
until a worker process picks it up.
Enhanced stability
When a worker process fails, service is not interrupted; the failure is
undetectable by the user because the kernel queues the requests while the WWW
service starts a new worker process for that application pool.
Faster process
Requests are processed faster because they are routed directly from the kernel
to the appropriate user-mode worker process instead of being routed between two
user-mode processes, i.e. the good old WinSock library and
the worker process.
How does it work with our framework?
All is encapsulated into a single class, named THttpApiServer
.
It provides one OnRequest
property event, in which all high level
process is to take place - it expects some input parameters, then will compute
the output content to be sent as response:
TOnHttpServerRequest = function(
const InURL, InMethod, InContent, InContentType: TSockData;
out OutContent, OutContentType, OutCustomHeader: TSockData): cardinal of object;
The HTTP Server
API is first initialized (if needed) during
THttpApiServer.Create
constructor call. The
HttpApi.dll
library (which is the wrapper around
http.sys
) is loaded dynamically: so if you are running an old
system (Windows XP SP1 for instance), you could still be able to use the
server.
We then register some URL matching the RESTful model, via
the THttpApiServer.AddUrl
method. In short, the
TSQLModel.Root
property is used to compute the RESTful
URL needed, just by the book.
You can register several TSQLRestServer
instances, each with
its own TSQLModel.Root
, if you need it.
If any of the two first point fails (e.g. if http.sys
is not
available, or if it was not possible to register the URLs), our framework will
fall back into using our THttpServer
class, which is a plain
Delphi multi-threaded server. It won't be said that we will let you down!
;)
Inside http.sys
all the magic is made... it will listen to any
incoming connection request, then handle the headers, then check against any
matching URL.
Our THttpApiServer
class will then receive the request, and pass
it to the TSQLRestServer
instance matching the incoming
URL request, via the THttpApiServer.OnRequest
event handler.
All JSON content will be processed, and a response will be retrieved from the
internal cache of the framework, or computed using the SQLite3 database
engine.
The resulting JSON content will be compressed using our very optimized
SynLZ
algorithm (20 times faster than Zip/Deflate for compression), if the client is
a Delphi application knowing about SynLZ - for an AJAX client, it
won't be compressed by default (even if you can enable the deflate algorithm -
which may slow down the server).
Then the response will be marked as to be sent back to the Client...
And http.sys
will handle all the communication by itself, leaving
the server free to process the next request.
When UAC strikes back again...
This works fine under XP. Performances are very good, and stability is there.
But... here comes the UAC nightmare again.
Security settings have changed since XP. Now only applications running with
Administrator rights can register URLs to http.sys
. That is, no
real application.
So the URL registration step will always fail with the default settings, under
Vista and Seven.
:(
We managed to create a workaround for this.
Our SynCrtSock
unit provides a dedicated method to authorize
a particular URL prefix to be registered by any user.
Therefore, a program can be easily created and called once with administrator
rights to make http.sys
work with our framework.
This could be for instance part of your Setup program.
Then when your server application will be launched (for instance, as a
background Windows
service), it will be able to register all needed URL.
Nice and easy.
Here is a sample program which can be launched to allow our
TestSQL3.dpr
to work as expected - it will allow any connection
via the 888 port, using TSQLModel.Root
set as 'root'
-
that is, an URL prefix of http://+:888/root/
as
expected by the kernel server:
program TestSQL3Register;
uses
SynCrtSock,
SysUtils;
// force elevation to Administrator under Vista/Seven
{$R VistaAdm.res}
begin
THttpApiServer.AddUrlAuthorize('root','888',false,'+'));
end.
Here it comes...
All this is to be officially released with our upcoming 1.13 version of the framework.
All the source code is already available from our Source Code repository.
Feedback and comments are welcome in our forum!