Releases: freitasjca/horse-provider-mormot
Release list
v1.0.7 — Horse 3.3.0 required
What's changed
Breaking dependency requirement
- Horse ≥ 3.3.0 — all previously fork-only Horse patches (
IHorseRawRequest/IHorseRawResponse,HORSE_PROVIDER_*define normalization, request/response shadow fields) are now included in the official HashLoad/horse 3.3.0 release. Thefreitasjca/horsefork is retired — remove it from yourboss.jsonand point athashload/horsedirectly.
boss.json
"github.com/HashLoad/horse": ">=3.3.0"
Integration test client
Added HorseMormotTestClient — companion to the existing test server, mirrors the CrossSocket provider test suite structure.v1.0.6
Requires horse >=3.2.101 (upstream 3.2.1 sync): implements IHorseRawRequest.PopulateHeaders, drops Web.HTTPApp from the request bridge (TMethodType now in Horse.Commons), adds the Listen overload family with bind-host support (socket backends use mORMot's host:port syntax; http.sys ignores host).
v1.0.5
TLSOPT-1/2 config fields (SSLKeyPassword, SSLCipherList) in Mormot.Config.pas; mORMot provider updates; TLS integration tests + certs; implementation notes + middleware compatibility docs
v1.0.4 — RFC 6265 cookie emission
BuildHeaders appends one 'Set-Cookie: ' line per Res.Cookie(...)/AddCookie entry to OutCustomHeaders (CRLF-joined, so multiple cookies are preserved); all attributes
incl. Max-Age round-trip. Adds Section K cookie tests and Section J wildcard SendFile tests (Delphi .dpr + Lazarus .lpr). Requires horse >=3.1.104.
v1.0.3
Ownership-aware multipart AddStream (PATCH-PARAM-1) resolving the file-part TMemoryStream leak; new response stream helpers (TryReadBodyStream /
ReleaseRawResponseContentStream); FPC PopulateMultipartFiles for RawWebRequest.Files; param/stream/multipart test suites for Delphi and Lazarus/FPC; implementation-notes doc update.
v1.0.2 — Multi-backend HTTP server + FPC/Lazarus compatibility
What's new
Multi-backend HTTP server
The provider now supports all three mORMot2 HTTP server backends, selectable via THorseMormotConfig.ServerKind or compile-time defines:
ServerKind |
mORMot class | Model |
|---|---|---|
mskThreadPool (default) |
THttpServer |
Socket thread-pool |
mskAsync |
THttpAsyncServer |
Non-blocking IOCP/epoll/kqueue event loop |
mskHttpApi |
THttpApiServer |
Windows http.sys kernel-mode (Windows only) |
Switch at runtime: Cfg.ServerKind := mskAsync; THorse.ListenWithConfig(9000, Cfg);
Or at compile time: -dHORSE_MORMOT_ASYNC / -dHORSE_MORMOT_HTTPAPI.
FPC/Lazarus compatibility
- Replace
TInterlocked.*(Delphi-only RTL) withInterlockedIncrement/InterlockedDecrement/InterlockedCompareExchangefree functions — the provider now compiles under
FPC 3.2.0+. - Minimum FPC version: 3.2.0 (Lazarus 2.2+ stable) — no trunk required (unlike the CrossSocket provider).
Lazarus IDE setup docs
Full step-by-step Lazarus setup added to README and doc/building-a-mormot-provider.md: mormot2 package compile, LazUtils dependency, search paths, static blob linker path, and the
TNextProc vs TProc distinction for FPC middleware.
Breaking changes
None — existing THorse.Listen(port) calls continue to use THttpServer (thread-pool) by default.
v1.0.0 — Initial release
v1.0.0 — Initial release
First public release of horse-provider-mormot — a mORMot2-backed transport provider for the Horse web framework.
What this is
A drop-in alternative to Horse's default Indy transport, activated by a single compiler define:
{$DEFINE HORSE_PROVIDER_MORMOT}
uses Horse;
begin
THorse.Get('/ping', procedure(Req: THorseRequest; Res: THorseResponse)
begin
Res.Send('pong');
end);
THorse.Listen(9000);
end.Routes, middleware, and THorseRequest / THorseResponse API are unchanged — switching transports does not require rewriting handlers. The mORMot2 THttpServer runs underneath instead of Indy's thread-per-connection model.
What's included
- Hybrid interface architecture —
IHorseRawRequest/IHorseRawResponsewith backward-compatibleTInterfacedWebRequest/TInterfacedWebResponseadapters so every existing Horse middleware (CORS, JWT, Jhonson, …) works unchanged. - Pre-pipeline request validation — URL length, header limits, body size, method allowlist, request-smuggling guards before the Horse pipeline is entered.
- Pooled
THorseContext— pre-warmed object pool, zero allocation on the hot path,Resetwipes every security-sensitive field between requests. - Graceful drain on shutdown —
SEC-30active-request counter;Listenreturns only after in-flight requests complete. - Application-type cross-product units — Console (default), VCL, Daemon (Windows Service + Linux daemon in one unit),
FPC.Daemon,FPC.LCL,FPC.HTTPApplication. Same.dprcompiles for both Windows and Linux targets. - TLS via OpenSSL — both
libssl 1.1.xand3.xaccepted at runtime;mormot2staticstatic-link variant supported for self-contained deployments.
mORMot2 interop notes
- Loopback
RemoteIPnormalised — mORMot2 defaultsRemoteIPLocalHostAsVoidInServerstoTrue, reporting loopback connections with an emptyRemoteIP. Horse middleware that consumesReq.RawWebRequest.RemoteAddr(rate limiters, audit loggers) needs a stable peer IP, so the provider sets this global toFalseat unit init. Seedoc/implementation-notes.mdfor the side effect this has on co-resident mORMot servers in the same process. - Multipart file uploads —
MultiPartFormDataDecodereturns inlineRawByteStringparts; the bridge synthesises aTMemoryStreamper file part and routes it throughContentFields.AddStream. See Known limitations below.
Requirements
| Dependency | Version | Notes |
|---|---|---|
| Delphi | 10.4 Sydney or later | Uses inline var, System.Threading |
| FPC | 3.2.0 or later | For the FPC.* application-type units |
| Horse | >= 3.1.98 |
PATCH-HORSE-2 three-axis define release |
| mORMot2 | recent master |
Install per synopse/mORMot2 instructions; on Delphi the mormot2static precompiled blobs are required |
Installation
boss install horse-provider-mormotmORMot2 itself is installed manually (clone + search paths). See the README for the full setup including the static-blob download.
Tested platforms
- Windows x86 / x64 (IOCP; also
http.sysviaTHttpApiServerswap) - Linux x64 (epoll)
- macOS ARM64
Known limitations
[FOLLOW-UP-MEM-1]— multipart-with-file uploads leak oneTMemoryStreamper request until the pool is torn down. Functionally correct (uploads work, content arrives intact), but memory accumulates under sustained upload load. Two proper fixes (pool-side stream tracking, or a Horse upstreamTObjectDictionary([doOwnsValues])patch) are documented indoc/implementation-notes.md— appropriate for low-throughput services, dev/test, and short-lived processes; not yet appropriate for high-throughput production upload endpoints.
Documentation
- README — install paths, activation, layout
- Architecture diagrams — request lifecycle, inheritance chains
- Implementation notes — provider-side design decisions, interop caveats
- Middleware compatibility matrix — per-middleware support status
Acknowledgements
- synopse/mORMot2 for the underlying HTTP server stack
- HashLoad/horse for the framework this plugs into
- freitasjca/horse-provider-crosssocket — the sister provider whose hybrid adapter architecture this release mirrors