Boilerplate HTTP Server for Synopse mORMot Framework
This project is embedding of HTML5 Boilerplate assets and settings into Synopse mORMot Framework:
mORMotBP
directory to your IDE library pathAssets.res
with all h5bp resources embedded:"..\Tools\assetslz" "$(PROJECTDIR)\Assets" "$(PROJECTDIR)\Assets.tmp"
"..\Tools\resedit" -D "$(PROJECTDIR)\Assets.res" rcdata ASSETS "$(PROJECTDIR)\Assets.tmp"
Replace
"..\Tools"
to mORMorBP relative or full directory location.
TSQLHttpServer
instance creation with TBoilerplateHTTPServer
YourHTTPServerInstance.LoadFromResource('Assets');
assetslz
and resedit
tools). This allows to build single file distribution.assetslz
tool.HTTP.sys
high-performance library (see .StaticRoot
property) and free your server threads for more interesting work.ETag/Last-Modified
or more user-friendly Last-Modified/If-Modified-Since
cache strategies.Expires
or Cache-Control: max-age
cache strategies.bpoEnableCacheBusting
and bpoEnableCacheBustingBeforeExt
options).bpoDelegateHidden
and bpoDelegateBlocked
options).CSP.pas
unit for details)..OnGetAsset
event)TBoilerplateHTTPServer = class(TSQLHttpServer)
To build or update Assets.res
file under Lazarus IDE use the next menu (when project file is opened):
Run / Build File
This menu command call pre-build.sh or pre-build.bat script which is use assetslz32
/assetslz64
and resedit32
/resedit64
tools to compress and embed assets under Linux/Windows environment.
Add the next FPC Lazarus IDE directive to any project file for ability to rebuild resource files:
{$IFDEF LINUX}
{%BuildCommand pre-build.sh $ProjPath()}
{$ENDIF}
{$IFDEF MSWINDOWS}
{%BuildCommand pre-build.bat "$ProjPath()"}
{$ENDIF}
Many thanks to Kiran Kurapaty with his BuildOptions package for Delphi 5 and Delphi 7. Based on his code the modified IDE packages for Delphi 5/6/7/2005/2006 were created to enable Build Events support on all Delphi IDE versions before Delphi 2007, where Build Events were introduced for the first time.
Use Component / Install Packages / Add IDE menu to install Build Events IDE extension:
Tools\BuildEvents\BuildEventsD5.bpl
for Delphi 5
Tools\BuildEvents\BuildEventsD6.bpl
for Delphi 6
Tools\BuildEvents\BuildEventsD7.bpl
for Delphi 7
Tools\BuildEvents\BuildEventsD2005.bpl
for Delphi 2005
Tools\BuildEvents\BuildEventsD2006.bpl
for Delphi 2006
With this build events and special .bat
file you can emulate DEBUG
and RELEASE
configurations.
Please see the Build Events readme for details.
DEBUG
configurationDue to 80 times slower compression nature of Zopfli algorithm it is not reasonable to use it during development and debug.
So for all debug configurations you can use fast and light level 1 compression with -GZ1 -B1
options of assetslz tool:
"..\Tools\assetslz" -GZ1 -B1 "$(PROJECTDIR)\Assets" "$(PROJECTDIR)\Assets.tmp"
"..\Tools\resedit" -D "$(PROJECTDIR)\Assets.res" rcdata ASSETS "$(PROJECTDIR)\Assets.tmp"
RELEASE
configurationFor release configuration it is recommended to turn on bpoForceHTTPS
, and set .StrictSSL
property to strictSSLOn
or
even strictSSLIncludeSubDomains
. Setup .ContentSecurityPolicy
property and validate it
with Security Headers service (see CSP.pas
unit for details).
Server
HTTP header on productionFor security reasons you can fully disable Server
and X-Powered-By
HTTP Headers on production.
To do this add NOXPOWEREDNAME
define to Project / Options / Conditional defines and rebuild all.
If you use HTTP.sys
API on Windows Server add or modify the next registry key to disable Server
HTTP header embedding (admin rights required):
Section: SYSTEM\CurrentControlSet\Services\HTTP\Parameters
Key: DisableServerHeader: DWORD = 2
Unfortunatelly default mORMot HTTP Server always use first registered compression in case when several compression options are available. To enable Brotli support for on-the-fly generated (HTML, JSON, XML, etc.) content do the next:
Turn off the default DEFLATE compression in mORMotHttpServer.pas
unit (line 76):
Before
{$define COMPRESSDEFLATE}
After
{.$define COMPRESSDEFLATE}
Then register HTTP Server compressions in Brotli, GZip
order:
uses
SynZip,
Brotli;
...
HttpServer.RegisterCompress(CompressBrotli);
HttpServer.RegisterCompress(CompressGZip);
You can provide your own computable Assets and redirects. This is usefull for:
/404.html
content service.Use BoilerplateHTTPServer.OnGetAsset
event handler and ensure that modifiable resources are handled with multi-thread support.
All external assets support ETag
, Last-Modified
cache strategies based on the provided Timestamp
property and can be statically upload to storage (for example to delegate content tranfer to low level http API).
The same method can be used to return custom redirections for specific URL paths.
TAssets
usageYou can embed any directories or files into your single project executable file.
This gives you an ability to distribute, scale and run only one file on yours production environments.
Load from resource and deploy any assets on your production when it started. TAssets
also checks files for modification timestamp and size changes before save to optimize disk IO operations.
For example you can compress and pack all you static assets into Assets.res
and additionally pack mustache view templates into separate Views.res
like this:
"..\Tools\assetslz" "$(PROJECTDIR)\Assets" "$(PROJECTDIR)\Assets.tmp"
"..\Tools\resedit" -D "$(PROJECTDIR)\Assets.res" rcdata ASSETS "$(PROJECTDIR)\Assets.tmp"
"..\Tools\assetslz" -E "$(PROJECTDIR)\Views" "$(PROJECTDIR)\Views.tmp"
"..\Tools\resedit" -D "$(PROJECTDIR)\Views.res" rcdata VIEWS "$(PROJECTDIR)\Views.tmp"
The -E
option for views means skip any compression because we needn't to compress mustache views.
Now you can embed both resources files into executable.
Add the next lines to you project file near {$R *.res}
or add both files to project:
{$R Assets.res}
{$R Views.res}
Then on production, you can extract views from executable like this:
procedure SaveViews;
var
Assets: TAssets;
begin
Assets.Init;
Assets.LoadFromResource('Views');
Assets.SaveAllIdentities('Views');
end;
With RegisterCustomOptions
method you can tweak different options for different HTTP URL paths.
For example, you can disable cache usage for you API JSON calls or some special pages like this:
HTTPServer.RegisterCustomOptions(
['/api/json', '/login', '/settings*'],
HTTPServer.Options - [bpoSetCachePublic] + [bpoSetCachePrivate,
bpoSetCacheNoCache, bpoSetCacheNoStore, bpoSetCacheMustRevalidate]);
The TBoilerplateHTTPServer
is fully test covered with mORMot Test Suite framework. Instead of classical TDD approach the Behavior-Driven Development (BDD) scenarios are used. Please see Tests\BoilerplateTests.pas
for details.
This project adheres to Semantic Versioning. Every release, along with the migration instructions, is documented on the GitHub Releases page.
The code is available under the MIT license.
Feel free to contact me at @gmail.com: eugene.ilyin