sgcOpenAPI 2026.6 — Eigenständiger OpenAPI-Server, Spec-First oder Code-First

· Versionen

Die nächste Version von sgcOpenAPI — Version 2026.6, geplant für Juni — liefert eine brandneue Komponente: TsgcHTTPServer_OpenAPI. Es handelt sich um eine einzelne, eigenständige Delphi-Komponente, die einen OpenAPI 3.0-Dienst mit einem eingebetteten HTTP-Server hostet. Platzieren Sie sie auf einem Formular, verweisen Sie auf eine Spezifikation (oder generieren Sie eine aus einer Delphi-Klasse mit RTTI-Attributen), setzen Sie Active := True, und Sie haben eine dokumentierte REST-API mit automatisch bereitgestellter Swagger UI.

Die wichtigste Neuerung ist, dass sgcOpenAPI sgcWebSockets nicht mehr benötigt, um einen HTTP-Server zu hosten. Die neue Komponente wird vollständig aus sgcOpenAPI ausgeliefert, paketiert und installiert. Wenn Sie sgcWebSockets bereits verwenden, funktioniert die bisherige Komponente TsgcWSServer_API_OpenAPI unverändert weiter — beide nutzen intern dieselbe Engine.

Was Sie in einer einzigen Komponente erhalten

TsgcHTTPServer_OpenAPI bündelt drei Dinge:

Schnellstart — das minimale Beispiel

Das ist alles, was Sie brauchen, um einen funktionierenden OpenAPI-Server mit Swagger UI zu hosten:

uses
  sgcHTTPServer_OpenAPI;

var
  oServer: TsgcHTTPServer_OpenAPI;
begin
  oServer := TsgcHTTPServer_OpenAPI.Create(nil);
  try
    oServer.Bindings.Add.Port := 8080;
    oServer.LoadFromFile('petstore.json');
    oServer.OnRequest := MyOnRequest;
    oServer.Active := True;
    Readln;
  finally
    oServer.Free;
  end;
end;

Rufen Sie http://localhost:8080/docs für die Swagger UI und http://localhost:8080/openapi.json für die Spezifikation auf. Jede in der Spezifikation definierte Operation wird mit der aufgelösten operationId und einem vollständig aufgebauten Anfragekontext an Ihren MyOnRequest-Handler weitergeleitet.

Spec-First — eine vorhandene OpenAPI-3.0-Datei laden

Wenn Sie bereits eine OpenAPI-3.0-Datei in JSON oder YAML haben (Petstore, einen internen API-Vertrag, ein öffentliches Schema, das Sie mocken möchten), ist Spec-First der schnellste Weg, sie bereitzustellen. LoadFromFile liest und parst die Spezifikation, erstellt eine Routing-Tabelle aus dem Abschnitt paths und vergleicht jede eingehende Anfrage damit.

Die operationId jeder Route ist der Dispatch-Schlüssel. Innerhalb von OnRequest behandeln Sie jede Operation der Reihe nach:

uses
  sgcHTTP_OpenAPI_Server, sgcHTTP_OpenAPI_Server_Engine,
  sgcHTTPServer_OpenAPI;

procedure TForm1.OnOpenAPIRequest(Sender: TObject;
  const aOperationId: string; const aContext: TsgcOpenAPIServerContext;
  var Handled: Boolean);
begin
  Handled := True;
  if aOperationId = 'listPets' then
    HandleListPets(aContext)
  else if aOperationId = 'getPetById' then
    HandleGetPetById(aContext)
  else if aOperationId = 'createPet' then
    HandleCreatePet(aContext)
  else
    Handled := False;
end;

procedure TForm1.HandleGetPetById(const aContext: TsgcOpenAPIServerContext);
var
  vId, vPetJSON: string;
begin
  vId := aContext.PathParamAsString('petId');
  vPetJSON := FPets.Values[vId];
  if vPetJSON <> '' then
    aContext.RespondJSON(200, vPetJSON)
  else
    aContext.RespondError(404, 'Not Found', 'Pet ' + vId + ' not found');
end;

Der TsgcOpenAPIServerContext bietet Ihnen typisierte Accessor-Methoden für alles in der Anfrage: PathParamAsString / PathParamAsInteger für Vorlagensegmente, QueryParamAsString / QueryParamAsInteger / QueryParamAsBoolean mit Standardwerten, BodyAsString / BodyAsJSON für den Anfragerumpf und HeaderValue für jeden eingehenden Header. Zum Antworten verwenden Sie die Hilfsmethoden RespondJSON(code, content) und RespondError(code, title, detail) oder setzen Response.Code, Response.ContentType und Response.Content direkt für volle Kontrolle.

Code-First — die Spezifikation aus einer Delphi-Klasse generieren

Wenn Sie den API-Vertrag lieber in Delphi schreiben und die Spezifikation generieren lassen möchten, dekorieren Sie eine Klasse mit RTTI-Attributen. TsgcOpenAPICodeFirstScanner durchläuft die Klasse, erstellt ein vollständiges OpenAPI-3.0-JSON-Dokument, und Sie laden dieses mit LoadFromString in den Server. Dies erfordert Delphi XE7 oder neuer (für erweitertes RTTI).

uses
  sgcHTTP_OpenAPI_Server_CodeFirst;

type
  [sgcServiceContract('Task Manager API',
    'A simple task management demo', '1.0.0')]
  [sgcRoute('/api/v1')]
  TTaskManagerService = class
  public
    [sgcHttpGet]
    [sgcRoute('/tasks')]
    [sgcSummary('List all tasks')]
    [sgcTag('Tasks')]
    [sgcResponse(200, 'A list of tasks')]
    procedure ListTasks([sgcFromQuery] const status: string); virtual;

    [sgcHttpPost]
    [sgcRoute('/tasks')]
    [sgcSummary('Create a new task')]
    [sgcTag('Tasks')]
    [sgcResponse(201, 'Task created successfully')]
    procedure CreateTask([sgcFromBody] const body: string); virtual;

    [sgcHttpGet]
    [sgcRoute('/tasks/{taskId}')]
    [sgcSummary('Get a task by ID')]
    [sgcTag('Tasks')]
    [sgcResponse(200, 'The requested task')]
    [sgcResponse(404, 'Task not found')]
    procedure GetTask([sgcFromPath][sgcRequired]
      const taskId: Integer); virtual;
  end;

Die Methodenrümpfe sind Stubs — sie existieren nur, damit der Compiler RTTI für sie ausgibt. Die eigentliche Arbeit erfolgt in OnRequest, dispatched anhand der operationId, die der Scanner aus jedem Methodennamen ableitet (ListTasks, CreateTask, GetTask…).

Übergeben Sie die Klasse beim Start an den Scanner und laden Sie die generierte Spezifikation in den Server:

uses
  sgcHTTP_OpenAPI_Server_CodeFirst, sgcHTTPServer_OpenAPI;

var
  oScanner: TsgcOpenAPICodeFirstScanner;
  oServer: TsgcHTTPServer_OpenAPI;
  vSpec: string;
begin
  oScanner := TsgcOpenAPICodeFirstScanner.Create;
  try
    vSpec := oScanner.GenerateSpec(TTaskManagerService);
  finally
    oScanner.Free;
  end;

  oServer := TsgcHTTPServer_OpenAPI.Create(nil);
  oServer.LoadFromString(vSpec);
  oServer.Bindings.Add.Port := 8081;
  oServer.OnRequest := MyOnRequest;
  oServer.Active := True;
end;

Die Attribute decken die üblichen Metadaten ab: sgcServiceContract füllt den OpenAPI-Block info, sgcRoute legt den Pfad auf Klassen- oder Methodenebene fest, sgcHttpGet / Post / Put / Delete / Patch / Head / Options wählt das Verb aus, sgcSummary und sgcDescription dokumentieren die Operation, sgcTag gruppiert sie in der Swagger UI, sgcResponse(code, description) deklariert jede Antwort, und sgcFromPath / FromQuery / FromBody / FromHeader zusammen mit sgcRequired beschreiben jeden Parameter.

Konfiguration — OpenAPIOptions

Die gesamte serverseitige Konfiguration befindet sich unter OpenAPIOptions, gruppiert in drei Unter-Optionen:

oServer.OpenAPIOptions.Endpoint.BasePath        := '/api';
oServer.OpenAPIOptions.Endpoint.ServeSpec       := True;   // /openapi.json
oServer.OpenAPIOptions.Endpoint.ServeSwaggerUI  := True;   // /docs

oServer.OpenAPIOptions.CORS.Enabled             := True;
oServer.OpenAPIOptions.CORS.AllowOrigins        := '*';
oServer.OpenAPIOptions.CORS.AllowHeaders        := 'Content-Type, Authorization';
oServer.OpenAPIOptions.CORS.AllowMethods        := 'GET, POST, PUT, DELETE, PATCH, OPTIONS';

oServer.OpenAPIOptions.Validation.ValidateRequest     := True;
oServer.OpenAPIOptions.Validation.ValidateRequestBody := True;
oServer.OpenAPIOptions.Validation.ValidateQueryParams := True;
oServer.OpenAPIOptions.Validation.ValidatePathParams  := True;
oServer.OpenAPIOptions.Validation.ValidateRequired    := True;

Bei aktivierter Validierung wird jede eingehende Anfrage anhand der in der Spezifikation deklarierten JSON-Schemas geprüft, bevor sie Ihren Handler erreicht — erforderliche Felder, Typen, Formate, Enums, Wertebereiche. Fehler lösen das Ereignis OnValidationError mit der Liste der Fehler und einer Markierung zum Akzeptieren oder Ablehnen der Anfrage aus.

Ereignisse

Die Komponente stellt sechs Ereignisse für den Lebenszyklus einer Anfrage bereit:

OnBeforeRequest: wird vor dem Dispatch ausgelöst; setzen Sie Accept := False, um mit 403 Forbidden abzulehnen. Nützlich für Rate-Limiting, Logging oder routenspezifische Sperren.

OnAuthenticate: wird vor dem Haupt-Handler ausgelöst; setzen Sie Authenticated := False, um mit 401 Unauthorized abzulehnen. Prüfen Sie Header, Cookies oder Abfrageparameter zur Entscheidung.

OnValidationError: wird ausgelöst, wenn die Validierung fehlschlägt; erhält die Liste der Fehler. Setzen Sie Continue := False, um mit 400 Bad Request abzulehnen.

OnRequest: das zentrale Dispatch-Ereignis. Sehen Sie sich aOperationId an, schreiben Sie die Antwort in aContext.Response, setzen Sie Handled := True.

OnAfterRequest: wird nach Rückkehr des Handlers ausgelöst — ideal für Metriken oder Audit-Logging.

OnException: wird ausgelöst, wenn eine unbehandelte Ausnahme aus Ihrem Handler heraussprudelt. Passen Sie aResponseCode an, wenn Sie etwas anderes als 500 Internal Server Error wünschen.

Demos

Mit sgcOpenAPI 2026.6 werden zwei vollständige Demos ausgeliefert, die beide ausschließlich die neue eigenständige Komponente verwenden — keine sgcWebSockets-Installation erforderlich:

Upgrade

Wenn Sie derzeit TsgcWSServer_API_OpenAPI mit sgcWebSockets verwenden, ändert sich nichts — Klasse, Eigenschaften und Ereignisse bleiben alle erhalten, und die Implementierung delegiert nun an dieselbe gemeinsame Engine, die auch die neue eigenständige Komponente antreibt. Sie können Ihren bestehenden Code unverändert beibehalten oder Formular für Formular zu TsgcHTTPServer_OpenAPI migrieren, um die sgcWebSockets-Abhängigkeit zu entfernen.

sgcOpenAPI 2026.6 wird im Juni auf der Download-Seite verfügbar sein.

Fragen, Feedback oder Migrationshilfe? Nehmen Sie Kontakt auf — Sie erhalten eine Antwort von den Personen, die den Code geschrieben haben.