Skip to main content

Horse Integration

Nidus ships a first-class middleware adapter for the Horse HTTP framework. The adapter unit is Nidus.Driver.Horse and the bundled Horse.ResponseCache adds HTTP-level response caching.

Quick setup​

uses
Horse,
Nidus.Driver.Horse;

begin
THorse
.Use(Nidus_Horse(TAppModule.Create))
.Listen(9000);
end;

Nidus_Horse(TAppModule) does two things:

  1. Calls GetNidus.Start(TAppModule) to bootstrap the Nidus module tree.
  2. Returns the Middleware callback that Horse calls on every request.

The middleware callback​

procedure Middleware(Req: THorseRequest; Res: THorseResponse; Next: TNextProc) is the core Horse middleware. Its flow:

  1. Skip Swagger / favicon routes — paths containing swagger or favicon.ico pass through immediately.
  2. Build IRouteRequest — _ResolverRouteRequest(Req) wraps all Horse request properties into TRouteRequest.
  3. Load route module — GetNidus.LoadRouteModule(PathInfo, LRequest) runs guards + pipes + route dispatch.
  4. Error mapping — ENidusException subclasses are mapped to their .Status code; other exceptions → HTTP 500.
  5. Dispose — GetNidus.DisposeRouteModule(PathInfo) is called in the finally block to free route-scoped module instances.

IRouteRequest fields​

TRouteRequest is constructed from the Horse request:

FieldSource
HeadersReq.Headers.Content
ParamsReq.Params.Content
QueryReq.Query.Content
BodyReq.Body
HostReq.RawWebRequest.Host
ContentTypeReq.RawWebRequest.ContentType
MethodReq.RawWebRequest.Method
PathInfoReq.RawWebRequest.PathInfo
ServerPortReq.RawWebRequest.ServerPort
AuthorizationReq.RawWebRequest.Authorization

HTTP methods supported​

The middleware only processes mtGet, mtPost, mtPut, mtPatch, mtDelete. Other methods (e.g. mtOptions) pass straight through to Next.

Charset / content-type override​

If you need a different charset:

THorse
.Use(Nidus_Horse('UTF-8')) // returns middleware only, no Start
.Use(Nidus_Horse(TAppModule.Create));

Horse.ResponseCache​

Horse.ResponseCache (Source/Horse/Horse.ResponseCache.pas) is a Nidus-owned Horse middleware for HTTP response caching.

Three ResponseCache overloads are exported from the unit:

// 1. Fluent options object
function ResponseCache(const AOptions: THorseResponseCacheOptions = nil): THorseCallback;

// 2. Quick TTL shorthand (defaults: MaxEntries=5000, VaryAuthorization=True)
function ResponseCache(const ATtlSeconds: Integer;
const AMaxEntries: Integer = 5000;
const AVaryAuthorization: Boolean = True): THorseCallback;

// 3. Route-prefix list with TTL (defaults: TTL=30, MaxEntries=5000, VaryAuthorization=True)
function ResponseCache(const ACacheRoutes: array of string;
const ATtlSeconds: Integer = 30;
const AMaxEntries: Integer = 5000;
const AVaryAuthorization: Boolean = True): THorseCallback;

THorseResponseCacheOptions is a fluent builder class (all methods return Self):

MethodDefaultDescription
TtlSeconds(n)30Cache entry lifetime in seconds
MaxEntries(n)5000Maximum number of cached responses
VaryAuthorization(b)TrueInclude Authorization header in the cache key
CacheAll(b)TrueCache all GET routes
CacheRoutes(routes)[]Cache only routes that start with the given prefixes
SkipRoutes(routes)['/swagger', '/favicon.ico']Never cache these path prefixes

Only GET requests are cached. Responses with a 2xx status code and a non-empty body are stored. The cache key is method:path?query|auth=<token> (lowercased).

Error JSON format​

Horse middleware wraps Nidus errors in JSON:

// ENidusException
{ "statusCode": 401, "message": "Unauthorized" }

// EHorseException
{ "statusCode": 404, "message": "Not found" }

// Generic Exception
{
"statusCode": "400",
"scope": "MyUnit",
"message": "Something went wrong"
}