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