OpenAPI-Server für Delphi

TsgcWSAPIServer_OpenAPI liefert das von dir geladene OpenAPI-3.x-Dokument aus, prüft jeden eingehenden Request dagegen, validiert den Request, bevor dein Handler läuft, und veröffentlicht das Dokument sowie eine Swagger-UI-Seite über denselben Port. Eine einzige Delphi-Komponente, angehängt an einen TsgcHTTPServer.

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

TsgcWSAPIServer_OpenAPI

Eine einzige Delphi-Komponente, die ein OpenAPI-Dokument in einen laufenden, validierten, selbstdokumentierenden REST-Server verwandelt.

Komponentenklasse

TsgcWSAPIServer_OpenAPI, deklariert in sgcWebSocket_Server_API_OpenAPI

Host-Server

Weise Server einen TsgcHTTPServer, einen TsgcHTTPRESTServer oder einen TsgcWebSocketHTTPServer zu. Der Host besitzt Port, Bindings und TLS.

Spec-Format

OpenAPI-3.0- und 3.1-Dokumente, von LoadFromFile und LoadFromString als JSON gelesen

Zwei Workflows

Spec-first aus einem bereits vorhandenen Dokument oder Code-first aus einer attributierten Delphi-Klasse. Code-first braucht Delphi XE7 oder neuer.

Edition

Wird mit sgcOpenAPI ausgeliefert. Innerhalb von sgcWebSockets gehört sie zur Enterprise-Edition, auf der Palette-Seite SGC OpenAPI.

Eingebaute Endpunkte

/openapi.json für das Dokument und /docs für Swagger UI, beide eingeschaltet in OpenAPIOptions.Endpoint

Spec-first oder Code-first, du entscheidest

Dieselbe Komponente läuft in beiden Modi. Starte von einem JSON-Vertrag oder beschreibe die API in Delphi und lass den Scanner das Dokument für dich generieren.

1. Spec-first

Lade petstore.json mit LoadFromFile, dispatche in OnRequest anhand der Operation-ID und starte den Server. Routing, Path- und Query-Parameter-Binding sowie Validierung kommen direkt aus dem Vertrag, du schreibst nur die Business-Logik.

Am besten für: Teams mit gemeinsamem Design-Vertrag, API-led Integration oder polyglotte Backends, in denen die Spec die Single Source of Truth ist.

2. Code-first

Annotiere eine einfache Delphi-Klasse mit sgcServiceContract, sgcRoute, sgcHttpGet und den Parameter-Attributen sgcFromPath / sgcFromQuery / sgcFromBody. TsgcOpenAPICodeFirstScanner.GenerateSpec baut das OpenAPI-Dokument aus der Klassen-RTTI, du übergibst es an LoadFromString, und derselbe /openapi.json-Endpunkt veröffentlicht es.

Am besten für: Rapid Prototyping, interne Services oder das Portieren einer bestehenden TIdHTTPServer-/DataSnap-REST-Oberfläche zu einer selbstdokumentierenden API.

Ein lauffähiger Server in 20 Zeilen

Erstelle die Komponente, lade ein Dokument, hänge es an einen HTTP-Server. Mehr Setup gibt es nicht.

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;

Was du out of the box bekommst: GET /pets/{petId} erreicht den obigen Handler mit aOperationId gleich getPetById, GET /openapi.json liefert das geladene Dokument, GET /docs öffnet Swagger UI. OpenAPIOptions.Endpoint.BasePath verschiebt die gesamte Oberfläche unter ein Prefix, TLS und HTTP/2 kommen vom Host-Server.

Die im OpenAPI-Dokument deklarierten Parameter werden über einen einzigen typisierten Context gelesen und konvertiert. Ist die Validierung aktiv, wird ein falscher Typ mit 400 Bad Request beantwortet, bevor dein Handler läuft.

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-Validierung, bevor dein Handler läuft

Jeder eingehende Request wird gegen die im Dokument deklarierten Schemas geprüft. Ein Fehlschlag wird mit einem Problem-Dokument im RFC-7807-Stil beantwortet, das jeden Fehler auflistet, und erreicht deinen Handler nur, wenn du es ausdrücklich zulässt.

Was geprüft wird

type, required, properties und additionalProperties, enum und const, minLength / maxLength, pattern, minimum / maximum mit ihren exklusiven Formen, multipleOf, items, minItems / maxItems, uniqueItems, nullable, not sowie oneOf / anyOf / allOf. Das Schlüsselwort format wird für date, date-time, email, ipv4, uri und uuid erzwungen.

Umfang wählen

Validation.ValidateRequest ist der Hauptschalter und validiert allein bereits jeden Bereich. Schränke ihn mit ValidateRequestBody, ValidateQueryParams, ValidatePathParams, ValidateHeaderParams und ValidateCookieParams ein. EnforceRequired gilt für jeden Bereich, den du wählst.

Das letzte Wort behalten

OnValidationError übergibt dir die Operation-ID und die vollständige Liste der Fehlschläge. Das Continue-Flag kommt als False an, der Request wird also abgelehnt, außer du setzt es bewusst auf True. Nach einem Laden nennt Validation.Warnings jedes Schema-Schlüsselwort, das das Dokument verwendet und das nicht erzwungen wird, eine leere Liste bedeutet also, dass nichts ungeprüft blieb.

JSON, die 400-Antwort der Engine
{
  "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, gesteuert von der Spec

Setze Security.EnforceSecurity, und die im Dokument deklarierten securitySchemes werden auf eingehende Requests angewendet. Du schreibst die Credential-Lookup-Logik, die Komponente parst den Request und antwortet mit 401 oder 403, wenn der Lookup ablehnt.

API Key

Gelesen aus Header, Query-Parameter oder Cookie, je nachdem, was das Scheme deklariert. OnValidateAPIKey erhält Scheme, Name, Location und Key und antwortet über Valid.

HTTP Basic

Der Authorization-Header wird für dich geparst. OnValidateBasic erhält Benutzername und Passwort und antwortet über Valid. Credentials werden nie geloggt.

Bearer und JWT

Security.JWTSecret verifiziert den Token. Ein HMAC-Secret wird unverändert verwendet, ein Wert, der -----BEGIN enthält, wird als PEM-Public-Key behandelt. ValidateExpiration, Issuer und Audience prüfen die Claims.

Dein eigener Verifier

Lass JWTSecret leer, dann wird der Token nur auf Vorhandensein geprüft, sodass OnValidateBearer ihn an deinen eigenen Token-Service weiterreichen und über Valid antworten kann.

401 oder 403

Ein fehlgeschlagener Request wird mit 401 beantwortet, oder mit 403, wenn er authentifiziert war und nur am Scope gescheitert ist. OnAuthenticate läuft zuerst und lehnt mit 401 ab, sobald du Authenticated zurücksetzt.

Mock, bevor der Code existiert

Mock.Enabled beantwortet eine Operation ohne Handler aus den eigenen Beispielen und Schemas des Dokuments, mit Mock.StatusCode, sodass ein Frontend-Team schon arbeiten kann, während die Implementierung noch entsteht.

Delphi, Bearer-Token von deinem eigenen Code verifiziert
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 eingebettet

Keine externe Abhängigkeit, kein Node.js, kein Doku-Build in der Deployment-Pipeline. Die Komponente schreibt die Seite selbst, und sie liest das Dokument, das dein Server tatsächlich ausliefert.

/openapi.json

Das von dir geladene Dokument, ausgeliefert, wenn Endpoint.ServeSpec aktiv ist. Immer im Einklang mit dem, was der Server tatsächlich routet. Richte jeden Client-Generator auf diese URL, sgcOpenAPI eingeschlossen.

/docs

Die interaktive Swagger-UI-Seite, ausgeliefert, wenn Endpoint.ServeSwaggerUI aktiv ist. Operationen ausprobieren, Schemas durchsehen, Beispiele lesen, alles gespeist von deinem eigenen laufenden Server.

Fixiert oder komplett offline

Die Seite lädt ihr CSS und JavaScript standardmäßig von einem öffentlichen CDN. Endpoint.SwaggerUIBaseURL fixiert eine Version, und Endpoint.SwaggerUIAssetsPath liefert swagger-ui.css und swagger-ui-bundle.js aus einem lokalen Ordner, sodass auch eine abgeschottete Maschine funktioniert.

Alles lebt unter OpenAPIOptions

Fünf persistente Sub-Objekte, alle im Object Inspector sichtbar, alle zur Laufzeit zuweisbar.

Endpoint

BasePath stellt jeder Route und beiden eingebauten Endpunkten ein Prefix voran. ServeSpec und ServeSwaggerUI schalten sie um. SpecFile wird lazy geladen, beim ersten Request, der keiner der beiden ist, verwende also LoadFromFile, wenn das Dokument schon beim allerersten Aufruf vollständig sein muss.

Validation

ValidateRequest plus die fünf Bereichs-Schalter sowie EnforceRequired. Warnings meldet nach jedem Laden die Schema-Schlüsselwörter, die das Dokument verwendet und die dieser Validator nicht erzwingt.

CORS

Enabled, AllowOrigins, AllowHeaders und AllowMethods. Die Engine prägt die Antworten für die Pfade, die ihrem Dokument gehören, gib dem Host-Server also dieselben Werte für die Pfade, die ihm gehören.

Security

EnforceSecurity, JWTSecret, ValidateExpiration, Issuer und Audience. Alles, was die eingebauten Prüfungen nicht entscheiden können, erreicht OnValidateAPIKey, OnValidateBasic oder OnValidateBearer.

Mock

Enabled und StatusCode. Eine Operation ohne Handler wird aus den eigenen Beispielen und Schemas des Dokuments beantwortet, sodass der Vertrag aufrufbar ist, bevor die Implementierung existiert.

Not Implemented, mit Absicht

Lass Handled auf False, dann antwortet die Engine mit 501 Not Implemented und nennt die Operation, statt mit einem 404, das wie ein Routing-Fehler aussieht.

Ein HTTP-Server, viele Oberflächen

TsgcWSAPIServer_OpenAPI dockt an denselben sgcWebSockets-HTTP-Server an, der auch deine WebSocket-Endpunkte, AI-/LLM-Streams und statischen Dateien hostet. Ein Port, ein TLS-Zertifikat, ein Log-Stream.

Server ist der Schalter

Es gibt keine Active-Eigenschaft. Das Zuweisen von Server hängt die Komponente an, das Setzen auf nil hängt sie ab, beides während der Host-Server weiterläuft. Abgehängt fallen die Pfade, die ihrem Dokument gehören, direkt an deinen gewöhnlichen Handler durch.

Die Komponente übernimmt den Server nie ganz

Jeder Request wird zuerst der Komponente angeboten, sie beantwortet aber nur die Pfade, die ihr Dokument deklariert. Alles andere erreicht wie bisher OnCommandGet, sodass ein Contract-first-Bereich neben handgeschriebenen Routen und statischen Inhalten aus DocumentRoot lebt, alles auf einem Port.

TLS und HTTP/2 des Hosts

Port, Bindings, Zertifikat und die HTTP/2-Aushandlung gehören dem Host-Server, die REST-Oberfläche erbt sie unverändert. Hängst du sie an einen TsgcHTTPRESTServer, gelten auch dessen CORS, Metriken, Health und Tenancy.

Typische Deployments

Öffentliche REST-APIs

Versioniert, vertraglich getestet, mit automatisch generierten SDKs, die deine Kunden von /openapi.json herunterladen können.

Interne Microservices

Service-zu-Service-Verträge, die Refactorings überleben — die Spec ist der Integrationstest.

Industrial-/IoT-Gateways

Edge-Geräte mit dokumentierter REST-Control-Plane plus MQTT- oder WebSocket-Telemetrie aus demselben Delphi-Binary.

Webhook-Empfänger

Jedes Provider-Webhook-Payload wird zu einem typisierten Pascal-Record — Stripe, GitHub, Twilio, Slack — mit Validierung und Idempotenz eingebaut.

Legacy-Modernisierung

Verpacke ein altes DataSnap- oder RemObjects-Backend hinter einer sauberen OpenAPI-Oberfläche, ohne die Business-Logik neu zu schreiben.

BFF (Backend-for-Frontend)

Aggregiere zwei oder drei Upstream-APIs hinter einer konsumentenförmigen Spec — deine SPA oder Mobile App spricht mit einem einzigen typisierten Endpunkt.

Kombiniert mit

OpenAPI-Parser

Lade jede externe Spec in dasselbe Modell, das auch der Server nutzt — gleiche Validierung, gleiches Typsystem, gleiche Security-Primitive.

Vorgefertigte Cloud-SDKs

Über 1.195 generierte SDKs für AWS, Azure, GCP, Stripe, GitHub, Kubernetes und mehr — dein Server kann jedes davon mit derselben Komponentenfamilie ansprechen.

sgcWebSockets

WebSocket, MQTT, AMQP, WebRTC, AI/LLM, IoT — alles, was der HTTP-Server neben deiner REST-Oberfläche hosten kann.

sgcSign

Signiere Request- und Response-Bodies mit XAdES / PAdES / CAdES für regulierte Branchen — eIDAS-Integrität auf jeder Operation.

Bestes Preis-Leistungs-Verhältnis: All-AccessAlle eSeGeCe-Produkte, inklusive Premium-Support, ab €1,059 pro Jahr.
All-Access-Preise ansehen

Baue deinen ersten OpenAPI-Server in Minuten

Lade die kostenlose Testversion herunter. Der komplette Server, beide UIs, jedes Auth-Schema — keine Feature-Limits, keine Zeitbombe während der Evaluierung.