OpenAPI-server voor Delphi

TsgcWSAPIServer_OpenAPI serveert het OpenAPI 3.x-document dat je laadt, toetst elk binnenkomend verzoek eraan, valideert het verzoek voordat je handler draait, en publiceert het document en een Swagger UI-pagina vanaf dezelfde poort. Eén Delphi-component, gekoppeld aan een TsgcHTTPServer.

OpenAPI 3.0 & 3.1
HTTP/2 + TLS 1.3
Swagger UI op /docs
Spec-first of Code-first

TsgcWSAPIServer_OpenAPI

Eén Delphi-component dat een OpenAPI-document omtovert tot een draaiende, gevalideerde, zelf-documenterende REST-server.

Componentklasse

TsgcWSAPIServer_OpenAPI, gedeclareerd in sgcWebSocket_Server_API_OpenAPI

Hostserver

Wijs aan Server een TsgcHTTPServer, een TsgcHTTPRESTServer of een TsgcWebSocketHTTPServer toe. De host bezit de poort, de bindings en TLS.

Specformaat

OpenAPI 3.0- en 3.1-documenten, gelezen als JSON door LoadFromFile en LoadFromString

Twee workflows

Spec-first vanuit een document dat je al hebt, of code-first vanuit een geattribueerde Delphi-klasse. Code-first vereist Delphi XE7 of nieuwer.

Editie

Wordt meegeleverd met sgcOpenAPI. Binnen sgcWebSockets hoort het bij de Enterprise-editie, op de paletpagina SGC OpenAPI.

Ingebouwde endpoints

/openapi.json voor het document en /docs voor Swagger UI, beide ingeschakeld in OpenAPIOptions.Endpoint

Spec-first of Code-first, jij kiest

Hetzelfde component draait in beide modi. Begin met een JSON-contract, of beschrijf de API in Delphi en laat de scanner het document voor je genereren.

1. Spec-first

Laad petstore.json met LoadFromFile, dispatch op de operation-id binnen OnRequest, en begin met serveren. Routing, path- en query-parameterbinding en validatie komen allemaal uit het contract, dus jij schrijft alleen de business logic.

Het beste voor: teams met een gedeeld design-contract, API-led integratie of polyglot back-ends waar de spec de bron van waarheid is.

2. Code-first

Voorzie een gewone Delphi-klasse van sgcServiceContract, sgcRoute, sgcHttpGet en de parameterattributen sgcFromPath / sgcFromQuery / sgcFromBody. TsgcOpenAPICodeFirstScanner.GenerateSpec bouwt het OpenAPI-document op uit de RTTI van de klasse, jij geeft het door aan LoadFromString, en hetzelfde /openapi.json-endpoint publiceert het.

Het beste voor: snel prototypen, interne services of het overzetten van een bestaande TIdHTTPServer / DataSnap REST-surface naar een zelf-documenterende API.

Een werkende server in 20 regels

Maak het component aan, laad een document, koppel het aan een HTTP-server. Dat is de hele setup.

Delphi
uses
  sgcHTTP_Server, sgcHTTP_OpenAPI_Server, sgcWebSocket_Server_API_OpenAPI;

procedure TForm1.FormCreate(Sender: TObject);
begin
  FServer := TsgcHTTPServer.Create(Self);
  FServer.Port := 8080;

  FOpenAPI := TsgcWSAPIServer_OpenAPI.Create(Self);
  FOpenAPI.LoadFromFile('petstore.json');      // any OpenAPI 3.x document
  FOpenAPI.OpenAPIOptions.Endpoint.ServeSpec := True;
  FOpenAPI.OpenAPIOptions.Endpoint.ServeSwaggerUI := True;
  FOpenAPI.OnRequest := OpenAPIRequest;
  FOpenAPI.Server := FServer;                // Server is the switch, there is no Active

  FServer.Active := True;
end;

// one event, dispatched by operation id
procedure TForm1.OpenAPIRequest(Sender: TObject;
  const aOperationId: string;
  const aContext: TsgcOpenAPIServerContext;
  var Handled: Boolean);
begin
  Handled := True;
  if aOperationId = 'getPetById' then
    aContext.RespondJSON(200, FPets.Values[aContext.PathParamAsString('petId')])
  else
    Handled := False;
end;

Wat je out of the box krijgt: GET /pets/{petId} bereikt de handler hierboven met aOperationId op getPetById, GET /openapi.json retourneert het document dat je hebt geladen, GET /docs opent Swagger UI. OpenAPIOptions.Endpoint.BasePath verplaatst het hele oppervlak onder een prefix, en TLS en HTTP/2 komen van de hostserver.

Parameters die in het OpenAPI-document zijn gedeclareerd, worden gelezen en geconverteerd via één getypeerde context. Met validatie ingeschakeld wordt een verkeerd type beantwoord met 400 Bad Request voordat je handler draait.

Delphi
// spec snippet
//   /pets:
//     get:
//       operationId: listPets
//       parameters:
//         - name: limit       in: query    schema: { type: integer, maximum: 100 }
//         - name: status      in: query    schema: { type: string, enum: [available, pending, sold] }
//         - name: X-Tenant-Id in: header   required: true

procedure TForm1.HandleListPets(const aContext: TsgcOpenAPIServerContext);
var
  vLimit:  Integer;
  vStatus: string;
  vTenant: string;
begin
  vLimit  := aContext.QueryParamAsInteger('limit', 20);        // default 20
  vStatus := aContext.QueryParamAsString ('status', 'available');
  vTenant := aContext.HeaderValue        ('X-Tenant-Id');   // required in the spec

  aContext.RespondJSON(200, PetRepo.List(vTenant, vStatus, vLimit));
end;

Schema-validatie voordat je handler draait

Elk binnenkomend verzoek wordt getoetst aan de schema's die het document declareert. Een mislukking wordt beantwoord met een RFC 7807-achtig problem-document dat elke fout vermeldt, en bereikt je handler nooit tenzij jij dat toestaat.

Wat wordt gecontroleerd

type, required, properties en additionalProperties, enum en const, minLength / maxLength, pattern, minimum / maximum met hun exclusieve varianten, multipleOf, items, minItems / maxItems, uniqueItems, nullable, not, en oneOf / anyOf / allOf. Het sleutelwoord format wordt afgedwongen voor date, date-time, email, ipv4, uri en uuid.

Kies de scope

Validation.ValidateRequest is de hoofdschakelaar en valideert op zichzelf elke scope. Vernauw dit met ValidateRequestBody, ValidateQueryParams, ValidatePathParams, ValidateHeaderParams en ValidateCookieParams. EnforceRequired blijft van toepassing op welke scope je ook kiest.

Jij hebt het laatste woord

OnValidationError geeft je de operation-id en de volledige lijst met mislukkingen. De vlag Continue komt binnen als False, dus het verzoek wordt geweigerd tenzij jij hem bewust op True zet. Na het laden noemt Validation.Warnings elk schema-sleutelwoord dat het document gebruikt maar dat niet wordt afgedwongen, dus een lege lijst betekent dat niets ongecontroleerd is gebleven.

JSON, de 400 die de engine schrijft
{
  "type":   "about:blank",
  "title":  "Bad Request",
  "status": 400,
  "detail": "Request validation failed",
  "errors": [
    "/email: invalid email format",
    "/age: must be <= 120",
    "/status: value not in enum"
  ]
}

Auth-schemes aangestuurd door de spec

Zet Security.EnforceSecurity aan en de securitySchemes die het document declareert worden toegepast op binnenkomende verzoeken. Jij schrijft de credential-lookup, het component parst het verzoek en antwoordt met 401 of 403 wanneer de lookup nee zegt.

API Key

Gelezen uit een header, een queryparameter of een cookie, afhankelijk van wat het scheme declareert. OnValidateAPIKey ontvangt het scheme, de naam, de locatie en de key, en antwoordt via Valid.

HTTP Basic

De Authorization-header wordt voor je geparst. OnValidateBasic ontvangt de gebruiker en het wachtwoord en antwoordt via Valid. Credentials worden nooit gelogd.

Bearer en JWT

Security.JWTSecret verifieert het token. Een HMAC-secret wordt zo gebruikt als het is, een waarde met -----BEGIN wordt behandeld als een PEM-publieke sleutel. ValidateExpiration, Issuer en Audience controleren de claims.

Je eigen verifier

Laat JWTSecret leeg en het token wordt alleen op aanwezigheid gecontroleerd, zodat OnValidateBearer het kan doorgeven aan je eigen tokenservice en kan antwoorden via Valid.

401 of 403

Een verzoek dat mislukt wordt beantwoord met 401, of met 403 wanneer het wel is geauthenticeerd maar alleen op scope tekortschiet. OnAuthenticate draait eerst en weigert met 401 zodra jij Authenticated leegmaakt.

Mock voordat de code bestaat

Mock.Enabled beantwoordt een operatie zonder handler vanuit de eigen voorbeelden en schema's van het document, met Mock.StatusCode, zodat een front-endteam kan werken terwijl de implementatie wordt geschreven.

Delphi, bearer-token geverifieerd door je eigen code
FOpenAPI.OpenAPIOptions.Security.EnforceSecurity := True;
FOpenAPI.OpenAPIOptions.Security.JWTSecret := GetSecretFromEnvironment;
FOpenAPI.OpenAPIOptions.Security.ValidateExpiration := True;
FOpenAPI.OpenAPIOptions.Security.Issuer   := 'https://auth.example.com';
FOpenAPI.OpenAPIOptions.Security.Audience := 'api.example.com';
FOpenAPI.OnValidateBearer := OpenAPIValidateBearer;

procedure TForm1.OpenAPIValidateBearer(Sender: TObject;
  const aToken: string;
  const aContext: TsgcOpenAPIServerContext; var Valid: Boolean);
begin
  Valid := MyTokenService.Verify(aToken);
end;

Swagger UI ingebouwd

Geen externe afhankelijkheid, geen Node.js, geen documentatiebuild in de deploy-pipeline. Het component schrijft de pagina zelf en leest het document dat je server daadwerkelijk serveert.

/openapi.json

Het document dat je hebt geladen, geserveerd wanneer Endpoint.ServeSpec aan staat. Altijd in stap met wat de server daadwerkelijk routeert. Wijs elke client-generator op deze URL, sgcOpenAPI inbegrepen.

/docs

De interactieve Swagger UI-pagina, geserveerd wanneer Endpoint.ServeSwaggerUI aan staat. Probeer operaties, blader door schema's, bekijk de voorbeelden, allemaal gevoed door je eigen draaiende server.

Vastgezet, of volledig offline

De pagina laadt standaard zijn CSS en JavaScript vanaf een publieke CDN. Endpoint.SwaggerUIBaseURL zet een versie vast, en Endpoint.SwaggerUIAssetsPath serveert swagger-ui.css en swagger-ui-bundle.js vanuit een lokale map, zodat ook een air-gapped machine werkt.

Alles leeft onder OpenAPIOptions

Vijf persistente sub-objecten, allemaal zichtbaar in de Object Inspector, allemaal toewijsbaar tijdens runtime.

Endpoint

BasePath zet een prefix voor elke route en beide ingebouwde endpoints. ServeSpec en ServeSwaggerUI schakelen ze in of uit. SpecFile wordt lui geladen, bij het eerste verzoek dat geen van beide is, dus gebruik LoadFromFile wanneer het document vanaf de allereerste aanroep compleet moet zijn.

Validation

ValidateRequest plus de vijf scope-schakelaars, en EnforceRequired. Warnings rapporteert, na elke keer laden, de schema-sleutelwoorden die het document gebruikt maar die deze validator niet afdwingt.

CORS

Enabled, AllowOrigins, AllowHeaders en AllowMethods. De engine stempelt de antwoorden op de paden die het eigen document bezit, dus geef de hostserver dezelfde waarden voor de paden die deze bezit.

Security

EnforceSecurity, JWTSecret, ValidateExpiration, Issuer en Audience. Alles wat de ingebouwde controles niet kunnen beslissen bereikt OnValidateAPIKey, OnValidateBasic of OnValidateBearer.

Mock

Enabled en StatusCode. Een operatie zonder handler wordt beantwoord vanuit de eigen voorbeelden en schema's van het document, zodat het contract aanroepbaar is voordat de implementatie bestaat.

Not Implemented, met opzet

Laat Handled op False staan en de engine antwoordt met 501 Not Implemented onder vermelding van de operatie, in plaats van een 404 die op een routeringsfout lijkt.

Eén HTTP-server, vele surfaces

TsgcWSAPIServer_OpenAPI koppelt aan dezelfde sgcWebSockets HTTP-server die je WebSocket-endpoints, AI/LLM-streams en statische bestanden host. Eén poort, één TLS-certificaat, één logstroom.

Server is de schakelaar

Er is geen Active-eigenschap. Door Server toe te wijzen koppel je het component, door deze op nil te zetten ontkoppel je het, allebei terwijl de hostserver blijft draaien. Ontkoppeld vallen de paden die het eigen document bezit direct door naar je gewone handler.

Het neemt de server nooit over

Elk verzoek wordt eerst aan het component aangeboden, en het beantwoordt alleen de paden die het eigen document declareert. Al het andere bereikt OnCommandGet zoals voorheen, dus een contract-first sectie leeft naast handgeschreven routes en statische content vanuit DocumentRoot, allemaal op één poort.

De TLS en HTTP/2 van de host

De poort, de bindings, het certificaat en de HTTP/2-onderhandeling horen bij de hostserver, dus het REST-oppervlak erft ze ongewijzigd. Koppel het aan een TsgcHTTPRESTServer en de CORS, metrics, health en tenancy van die server gelden ook.

Typische deployments

Publieke REST API's

Versioned, contract-getest, met auto-gegenereerde SDK's die je klanten kunnen downloaden vanaf /openapi.json.

Interne microservices

Service-tot-service contracten die refactors overleven — de spec is de integratietest.

Industriële / IoT-gateways

Edge-devices die een gedocumenteerd REST-control plane plus een MQTT- of WebSocket-telemetrie-surface bieden vanuit dezelfde Delphi-binary.

Webhook-ontvangers

De webhook-payload van elke provider wordt een getypeerde Pascal-record — Stripe, GitHub, Twilio, Slack — met validatie en idempotentie ingebouwd.

Legacy-modernisering

Verpak een oude DataSnap- of RemObjects-back-end achter een schone OpenAPI-surface zonder de business logic te herschrijven.

BFF (Backend-for-Frontend)

Aggregeer twee of drie upstream-API's achter één spec die past bij de consument — je SPA of mobiele app praat met één getypeerde endpoint.

Combineer met

OpenAPI Parser

Laad elke externe spec in hetzelfde model dat de server gebruikt — dezelfde validatie, hetzelfde typesysteem, dezelfde security-primitives.

Kant-en-klare cloud-SDK's

Meer dan 1.195 gegenereerde SDK's voor AWS, Azure, GCP, Stripe, GitHub, Kubernetes en meer — je server kan ze allemaal aanroepen met dezelfde componentfamilie.

sgcWebSockets

WebSocket, MQTT, AMQP, WebRTC, AI/LLM, IoT — alles wat de HTTP-server naast je REST-surface kan hosten.

sgcSign

Onderteken request- en response-bodies met XAdES / PAdES / CAdES voor gereguleerde sectoren — eIDAS-grade integriteit op elke operatie.

De beste deal: All-AccessElk eSeGeCe-product, inclusief Premium-ondersteuning, vanaf €1,059 per jaar.
Bekijk de All-Access-prijzen

Bouw je eerste OpenAPI-server in minuten

Download de gratis proefversie. De volledige server, beide UI's, elk auth-schema — geen featurebeperkingen, geen tijdbom tijdens de evaluatie.