Skip to content

Kitto.Web.Rest ​

Opt-in REST/JSON API for a KittoX application. Exposes the same views used by the HTML/HTMX GUI as a parallel tree under /api/v4/{ViewName} with real HTTP verbs, sharing the CRUD service layer (Kitto.Web.Data.Service) — same model, same business rules, same ACL as the GUI.

This unit is NOT part of the core umbrella (Kitto.Html.All): an application enables the REST API by adding it to its UseKitto.pas, exactly as it opts into Kitto.Web.Enterprise. It depends only on the RTL System.JSON (no third-party JSON framework); delphi-neon support (typed DTOs, OpenAPI) is a separate opt-in unit added later.

Endpoints (base path /api/v4/{ViewName}), all exempt from the navigation guard ([TKXNavigable] — a REST client does not send X-KittoX): GET /api/v4/{V} list -> { "data": [...], "total": N } GET /api/v4/{V}/{id} read one -> { ... } | 404 POST /api/v4/{V} create -> 201 + created record PUT /api/v4/{V}/{id} full update -> 200 + updated record PATCH /api/v4/{V}/{id} partial upd. -> 200 + updated record DELETE /api/v4/{V}/{id} delete -> 204

Errors on /api are rendered as a JSON envelope { error, code, field? } with a real HTTP status (see TKXApiErrorFilter). See KittoX_RestServer.md.

IKXApiSerializer interface ​

Serialization seam between the REST handler and a concrete JSON provider. The default provider uses System.JSON; a Neon-based provider can replace it via SetKXApiSerializer. The serializer is PURE — it never fires business rules (those run in the service layer); ParseInto only maps JSON to record field values.

pascal
function SerializeStore(const AStore: TKViewTableStore;

Serializes a store page as a JSON list envelope { "data": [...], "total": N }.

pascal
function SerializeRecord(const ARecord: TKViewTableRecord): string;

Serializes a single record as a JSON object.

pascal
procedure ParseInto(const AJSON: string;

Parses a JSON object body and applies its members to the record's fields (through TKXDataService.ApplyFieldValue). No business rules here.

TKXSystemJSONSerializer class ​

Default serializer built on the RTL System.JSON DOM (correct escaping, zero deps).

pascal
function SerializeStore(const AStore: TKViewTableStore;

Serializes a store page as a JSON list envelope { "data": [...], "total": N }.

pascal
function SerializeRecord(const ARecord: TKViewTableRecord): string;

Serializes a single record as a JSON object.

pascal
procedure ParseInto(const AJSON: string;

Parses a JSON object body and applies its members to the record's fields (via TKXDataService.ApplyFieldValue); unknown members are ignored.

TKXApiHandlerBase class ​

REST API handler for a data view. All endpoints are virtual so an application can subclass and RegisterOverride to customize a single verb.

pascal
procedure GetList([TKXPathParam('ViewName')] const AViewName: string);

GET list: envelope { data, total } with ?start=&limit=&sort=&dir=.

pascal
procedure GetItem([TKXPathParam('ViewName')] const AViewName: string;

GET one record by key (404 if absent).

pascal
procedure PostItem([TKXPathParam('ViewName')] const AViewName: string);

POST create: body = JSON record; 201 + created record.

pascal
procedure PutItem([TKXPathParam('ViewName')] const AViewName: string;

PUT full update: 200 + updated record.

pascal
procedure PatchItem([TKXPathParam('ViewName')] const AViewName: string;

PATCH partial update (only the fields present in the body): 200 + updated record.

pascal
procedure DeleteItem([TKXPathParam('ViewName')] const AViewName: string;

DELETE by key: 204.

TKXApiAuthHandler class ​

Token endpoint for stateless REST clients. POST /api/v4/token with a JSON body { "username", "password", "database"? } authenticates via the app's authenticator and returns a Bearer JWT: { "token_type":"Bearer", "access_token":"<jwt>" }. Anonymous (no token needed to obtain one). Requires Auth: JWT (the only authenticator that issues tokens).

pascal
procedure PostToken;

Authenticates the JSON body {username,password,database?} and returns a Bearer JWT; 401 on invalid credentials.

TKXApiCorsHandler class ​

Matches the CORS preflight (OPTIONS) on the two /api/v4 path shapes so the request enters the filter chain, where TKXCorsFilter answers it. If CORS is disabled (or the origin is not allowed) the filter does nothing and these no-op methods return a bare 204. Anonymous: a preflight carries no credentials.

pascal
procedure PreflightCollection([TKXPathParam('ViewName')] const AViewName: string);

CORS preflight for the collection path /api/v4/{ViewName}.

pascal
procedure PreflightItem([TKXPathParam('ViewName')] const AViewName: string;

CORS preflight for the item path /api/v4/{ViewName}/{id}.

TKXCorsFilter class ​

Adds CORS headers to /api/v4 responses and answers the preflight, when the request's Origin is allowed by Server/CORS/AllowedOrigins in Config.yaml ('*' or a comma-separated list; empty = CORS disabled). Optional Server/CORS/AllowCredentials: True emits Access-Control-Allow-Credentials.

pascal
procedure BeforeInvoke(const AContext: IKXRequestContext);

For an allowed cross-origin /api request, emits the CORS response headers and, on an OPTIONS preflight, answers 204 and short-circuits the chain.

pascal
procedure AfterInvoke(const AContext: IKXRequestContext);

No-op.

pascal
function OnException(const AContext: IKXRequestContext;

Does not handle exceptions (always returns False).

TKXApiErrorFilter class ​

Renders any exception escaping an /api/v4 request as a JSON error envelope { error, code, field? } with a real HTTP status (EKXDataError carries its own; rule/validation errors map to 422; anything else to 500). Registered after the core filters so its OnException runs first: for /api it wins, for every other path it returns False and the HTML error dialog handles it.

pascal
procedure BeforeInvoke(const AContext: IKXRequestContext);

No-op.

pascal
procedure AfterInvoke(const AContext: IKXRequestContext);

No-op.

pascal
function OnException(const AContext: IKXRequestContext;

For an /api request, renders E as a JSON error envelope { error, code, field? } with a real HTTP status and returns True; returns False for any other path.

Routines ​

pascal
function KXApiSerializer: IKXApiSerializer;

The active API serializer (lazily defaults to TKXSystemJSONSerializer).

pascal
procedure SetKXApiSerializer(const AValue: IKXApiSerializer);

Overrides the active API serializer (e.g. a Neon-based one).

Released under Apache License, Version 2.0.