feat: integrate CrossSocket / mORMot transport providers + PATCH-HORSE-2 three-axis defines + bilingual docs - #462
Merged
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Integrate CrossSocket / mORMot transport providers + PATCH-HORSE-2 three-axis defines + bilingual docs
Summary
This PR proposes integrating of work from the
freitasjca/horsefork into upstream. The fork ships releases used in production today and underpins two transport-provider packages (horse-provider-crosssocket v1.0.8andhorse-provider-mormot v1.0.1). Every change is additive — no existing method is removed, renamed, or given a different signature, and every existing.dproj/.lpicontinues to compile unchanged.I chose to submit this as one PR rather than several themed ones because the changes form a coherent design and most have non-trivial inter-dependencies. If you'd prefer the work split (e.g. provider-scaffolding separately from docs), I'm happy to repackage.
What this proposes
The PR's four commits are independently legible — each builds on the previous:
64cd1c4feat: CrossSocket high-performance provider integrationHorse.Provider.RawInterfaces+Horse.Provider.RawAdapters(new units enabling external-provider plug-in via lightweight interfaces); nil-guard branches inHorse.Request/Horse.Responsefor non-Indy paths;ListenWithConfig+Execute+MaxConnectionsonHorse.Provider.Abstractca41d80feat(horse): PATCH-HORSE-2 three-axis defines + bilingual doc tree (v3.1.98)Horse.pas(Provider × Application type × Host-managed); G1–G8 backwards-compatibility contract; bilingualdoc/tree (EN + PT-BR)e8e346ffeat: HORSE_PROVIDER_MORMOT guards + HORSE_DAEMON umbrella docs + EN/PT-BR doc sync (v3.1.99){$MESSAGE FATAL}guards forHORSE_PROVIDER_MORMOT × HORSE_HOST_*(mirrors existing CROSSSOCKET guards); HORSE_DAEMON umbrella documentation; OpenSSL per-OS deployment section6884f57chore(release): bump boss.json version to 3.1.99boss.jsonversion updateBackwards-compatibility guarantee (the G1–G8 contract)
A formal contract is embedded at the top of
src/Horse.pas— eight guarantees the maintainer of this PR (and any future change to that file) must preserve:HORSE_*define still works and resolves to the same Application-type / Provider as before. (HORSE_CROSSSOCKET,HORSE_VCL,HORSE_DAEMON,HORSE_LCL,HORSE_APACHE,HORSE_ISAPI,HORSE_CGI,HORSE_FCGIall carried as aliases.)fphttpserver+ HTTPApplication (the no-define default) on FPC is unchanged.HORSE_NOPROVIDERstill selects the abstract base.{$MESSAGE FATAL}block. The narrowing in PATCH-HORSE-2 only expands what's accepted.THorseProvidertype alias resolves to the same concrete class for every legacy-define input as before.Console/VCL/Daemonproviders on Delphi remain Indy-backed when no Provider define is set.Daemon/HTTPApplication/LCLproviders on FPC remainfphttpserver-backed when no Provider define is set.If any of these fail under any combination of defines, the change is a regression and shouldn't merge. I've validated all eight across the fork's 18-month deployment history.
Architecture in three paragraphs
The provider abstraction. Originally Horse hard-coded Indy as the only Delphi transport and
fphttpserveras the only FPC transport. This PR introducesIHorseRawRequest/IHorseRawResponse— lightweight interfaces (~15 methods total) that a provider implements by wrapping its own native request/response types. TheTInterfacedWebRequest/TInterfacedWebResponseadapter classes give back backwards-compatibleTWebRequest/TWebResponseso existing middleware (Horse.CORS,Jhonson, JWT, etc.) sees the API it expects. Indy andfphttpservercontinue to work via their existing code paths — the interfaces only fire whenFWebRequest/FWebResponsearenil.The three-axis define normalization. Existing
HORSE_*defines conflated three orthogonal choices: what HTTP transport (Indy/fphttpserver/ new providers), how the binary is packaged (Console/VCL/Daemon/ etc.), and whether the binary self-hosts or is host-managed (Apache/ISAPI/CGI/FCGI). PATCH-HORSE-2 splits these into three namespaces (HORSE_PROVIDER_*,HORSE_APPTYPE_*,HORSE_HOST_*) and adds a two-stage selection chain. Legacy defines remain accepted via a translation block at the top ofHorse.pas. The{$MESSAGE FATAL}block is narrowed to combinations that are architecturally impossible (e.g. anyHORSE_PROVIDER_*+ anyHORSE_HOST_*) — combinations that were previously rejected only because the flat chain couldn't express them (e.g.HORSE_CROSSSOCKET + HORSE_VCL) are now valid.Documentation. The fork has built up a complete
doc/tree over the last year — getting-started, routing, request-response, middleware, providers, deployment cheatsheet, compiler-support, middleware ecosystem, writing-middleware guide. Every page exists as EN + PT-BR mirrors. The OpenSSL deployment section, the HORSE_DAEMON umbrella note (Windows Service vs Linux systemd as two binary shapes of the same define), and the kernel-API annotations on the compiler-support matrix are all there.Evidence the design works in production
freitasjca/horse-provider-crosssocketfreitasjca/horse >= 3.1.99freitasjca/horse-provider-mormotfreitasjca/horse >= 3.1.99freitasjca/Delphi-Cross-SocketBoth provider packages have 11/11 integration tests passing against the fork's
v3.1.99.Test plan
samples/projects compile unchangedHorse.Provider.FPC.*unitsCompanion repos this unblocks
Once merged, these can switch their
boss.jsonfromfreitasjca/horsetoHashLoad/horse:freitasjca/horse-provider-crosssocket— drops the fork dependencyfreitasjca/horse-provider-mormot— drops the fork dependencyI've staged the corresponding consumer-side
boss.jsonchange but won't push it until this lands.