Skip to content

feat: integrate CrossSocket / mORMot transport providers + PATCH-HORSE-2 three-axis defines + bilingual docs - #462

Merged
viniciussanchez merged 2 commits into
HashLoad:masterfrom
freitasjca:master
Jun 1, 2026
Merged

feat: integrate CrossSocket / mORMot transport providers + PATCH-HORSE-2 three-axis defines + bilingual docs#462
viniciussanchez merged 2 commits into
HashLoad:masterfrom
freitasjca:master

Conversation

@freitasjca

@freitasjca freitasjca commented Jun 1, 2026

Copy link
Copy Markdown
Contributor

Integrate CrossSocket / mORMot transport providers + PATCH-HORSE-2 three-axis defines + bilingual docs

Summary

This PR proposes integrating of work from the freitasjca/horse fork into upstream. The fork ships releases used in production today and underpins two transport-provider packages (horse-provider-crosssocket v1.0.8 and horse-provider-mormot v1.0.1). Every change is additive — no existing method is removed, renamed, or given a different signature, and every existing .dproj / .lpi continues 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:

# Commit What it adds
1 64cd1c4 feat: CrossSocket high-performance provider integration Horse.Provider.RawInterfaces + Horse.Provider.RawAdapters (new units enabling external-provider plug-in via lightweight interfaces); nil-guard branches in Horse.Request / Horse.Response for non-Indy paths; ListenWithConfig + Execute + MaxConnections on Horse.Provider.Abstract
2 ca41d80 feat(horse): PATCH-HORSE-2 three-axis defines + bilingual doc tree (v3.1.98) Three-axis define normalization in Horse.pas (Provider × Application type × Host-managed); G1–G8 backwards-compatibility contract; bilingual doc/ tree (EN + PT-BR)
3 e8e346f feat: HORSE_PROVIDER_MORMOT guards + HORSE_DAEMON umbrella docs + EN/PT-BR doc sync (v3.1.99) Four {$MESSAGE FATAL} guards for HORSE_PROVIDER_MORMOT × HORSE_HOST_* (mirrors existing CROSSSOCKET guards); HORSE_DAEMON umbrella documentation; OpenSSL per-OS deployment section
4 6884f57 chore(release): bump boss.json version to 3.1.99 One-line boss.json version update

Backwards-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:

  • G1. Every existing legacy 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_FCGI all carried as aliases.)
  • G2. Indy + Console (the no-define default) on Delphi is unchanged.
  • G3. fphttpserver + HTTPApplication (the no-define default) on FPC is unchanged.
  • G4. HORSE_NOPROVIDER still selects the abstract base.
  • G5. No existing combination of legacy defines is newly rejected by the {$MESSAGE FATAL} block. The narrowing in PATCH-HORSE-2 only expands what's accepted.
  • G6. The THorseProvider type alias resolves to the same concrete class for every legacy-define input as before.
  • G7. Default Console / VCL / Daemon providers on Delphi remain Indy-backed when no Provider define is set.
  • G8. Default Daemon / HTTPApplication / LCL providers on FPC remain fphttpserver-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 fphttpserver as the only FPC transport. This PR introduces IHorseRawRequest / IHorseRawResponse — lightweight interfaces (~15 methods total) that a provider implements by wrapping its own native request/response types. The TInterfacedWebRequest / TInterfacedWebResponse adapter classes give back backwards-compatible TWebRequest / TWebResponse so existing middleware (Horse.CORS, Jhonson, JWT, etc.) sees the API it expects. Indy and fphttpserver continue to work via their existing code paths — the interfaces only fire when FWebRequest / FWebResponse are nil.

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 of Horse.pas. The {$MESSAGE FATAL} block is narrowed to combinations that are architecturally impossible (e.g. any HORSE_PROVIDER_* + any HORSE_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

Repo Latest release Depends on
freitasjca/horse-provider-crosssocket v1.0.8 freitasjca/horse >= 3.1.99
freitasjca/horse-provider-mormot v1.0.1 freitasjca/horse >= 3.1.99
freitasjca/Delphi-Cross-Socket v1.0.3 Provides the mTLS-bearing fork release

Both provider packages have 11/11 integration tests passing against the fork's v3.1.99.

Test plan

  • All existing Horse tests pass on the fork's CI (Delphi 11 Alexandria, Delphi 12 Athens)
  • CrossSocket provider — 11/11 integration tests passing (POST upload, multipart, cookies, RawWebRequest adapter, RemoteAddr, etc.)
  • mORMot2 provider — 11/11 integration tests passing (same test surface)
  • All existing samples/ projects compile unchanged
  • Linux daemon build (Delphi cross-compile to Linux64) works for both CrossSocket and mORMot provider paths
  • FPC 3.2.0 builds work via the Horse.Provider.FPC.* units

Companion repos this unblocks

Once merged, these can switch their boss.json from freitasjca/horse to HashLoad/horse:

  • freitasjca/horse-provider-crosssocket — drops the fork dependency
  • freitasjca/horse-provider-mormot — drops the fork dependency

I've staged the corresponding consumer-side boss.json change but won't push it until this lands.

@viniciussanchez
viniciussanchez merged commit b0e35b1 into HashLoad:master Jun 1, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants