La prochaine version de sgcOpenAPI, la version 2026.6, prévue pour juin, livre un serveur OpenAPI 3.0 que vous pouvez héberger sans installer sgcWebSockets. Deux composants s'en chargent : TsgcHTTPServer, le serveur HTTP basé sur Indy, et TsgcWSAPIServer_OpenAPI, le composant API que vous lui attachez. Pointez le composant API vers une spécification (ou générez-en une à partir d'une classe Delphi avec des attributs RTTI), affectez sa propriété Server, démarrez le serveur HTTP, et vous obtenez une API REST documentée avec Swagger UI servi automatiquement.
Le changement principal est que sgcOpenAPI n'a plus besoin de sgcWebSockets pour héberger un serveur HTTP. Les deux composants sont livrés, packagés et installés entièrement depuis sgcOpenAPI. Si vous utilisez déjà sgcWebSockets, le composant TsgcWSServer_API_OpenAPI que vous connaissez continue de fonctionner sans changement, car c'est la même classe : les deux produits la construisent à partir du même moteur.
Ce que vous obtenez
La paire apporte trois éléments :
- Un serveur HTTP (basé sur Indy),
TsgcHTTPServer, avec les propriétés habituellesBindings,PortetActive. - Le moteur OpenAPI : analyse de la spécification, routage par modèle de chemin avec des segments
{paramName}, validation JSON-Schema, CORS, gestion des exceptions. - Deux points de terminaison servis automatiquement : la spécification sur
/openapi.jsonet un Swagger UI sur/docs. Les deux sont activés par défaut et peuvent être basculés dansOpenAPIOptions.Endpoint.
Démarrage rapide — l'exemple minimal
Voici tout ce dont vous avez besoin pour héberger un serveur OpenAPI fonctionnel avec Swagger UI. Notez que le composant API n'a pas de propriété Active qui lui soit propre : c'est l'affectation de Server qui l'attache, et l'affectation de nil le détache pendant que le serveur HTTP continue de tourner.
uses
sgcHTTP_Server, sgcWebSocket_Server_API_OpenAPI;
var
oServer: TsgcHTTPServer;
oOpenAPI: TsgcWSAPIServer_OpenAPI;
begin
oServer := TsgcHTTPServer.Create(nil);
oOpenAPI := TsgcWSAPIServer_OpenAPI.Create(nil);
try
oServer.Bindings.Add.Port := 8080;
oOpenAPI.LoadFromFile('petstore.json');
oOpenAPI.OnRequest := MyOnRequest;
oOpenAPI.Server := oServer;
oServer.Active := True;
Readln;
finally
oOpenAPI.Free;
oServer.Free;
end;
end;
Naviguez vers http://localhost:8080/docs pour le Swagger UI et http://localhost:8080/openapi.json pour la spécification. Chaque opération définie dans la spécification est routée vers votre gestionnaire MyOnRequest avec l'operationId résolu et un contexte de requête entièrement construit.
Spec-First — charger un fichier OpenAPI 3.0 existant
Si vous avez déjà un fichier OpenAPI 3.0 au format JSON (Petstore, un contrat d'API interne, un schéma public que vous souhaitez simuler), la méthode spec-first est la plus rapide pour le servir. LoadFromFile lit et analyse la spécification, construit une table de routage à partir de la section paths, et fait correspondre chaque requête entrante à celle-ci. Le serveur lit du JSON, convertissez donc d'abord un contrat YAML, par exemple avec sgcOpenAPI.exe.
L'operationId de chaque route est la clé de dispatch. À l'intérieur de OnRequest, vous traitez chaque opération tour à tour :
uses
sgcHTTP_Server, sgcHTTP_OpenAPI_Server,
sgcHTTP_OpenAPI_Server_Engine, sgcWebSocket_Server_API_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;
Le TsgcOpenAPIServerContext vous donne des accesseurs typés pour tout ce qui se trouve dans la requête : PathParamAsString / PathParamAsInteger pour les segments à modèle, QueryParamAsString / QueryParamAsInteger / QueryParamAsBoolean avec des valeurs par défaut, BodyAsString / BodyAsJSON pour le corps de la requête, et HeaderValue pour tout en-tête entrant. Pour répondre, utilisez les helpers RespondJSON(code, content) et RespondError(code, title, detail), ou définissez directement Response.Code, Response.ContentType et Response.Content pour un contrôle complet.
Code-First — générer la spécification à partir d'une classe Delphi
Si vous préférez écrire le contrat d'API en Delphi et laisser la spécification être générée, décorez une classe avec des attributs RTTI. TsgcOpenAPICodeFirstScanner parcourt la classe, construit un document JSON OpenAPI 3.0 complet, et vous le chargez dans le serveur avec LoadFromString. Cela nécessite Delphi XE7 ou plus récent (pour le RTTI étendu).
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;
Les corps des méthodes sont des stubs — ils n'existent que pour que le compilateur émette le RTTI correspondant. Le vrai travail se fait dans OnRequest, dispatché par l'operationId que le scanner dérive de chaque nom de méthode (ListTasks, CreateTask, GetTask…).
Transmettez la classe au scanner au démarrage et chargez la spécification générée dans le serveur :
uses
sgcHTTP_Server, sgcHTTP_OpenAPI_Server_CodeFirst,
sgcWebSocket_Server_API_OpenAPI;
var
oScanner: TsgcOpenAPICodeFirstScanner;
oServer: TsgcHTTPServer;
oOpenAPI: TsgcWSAPIServer_OpenAPI;
vSpec: string;
begin
oScanner := TsgcOpenAPICodeFirstScanner.Create;
try
vSpec := oScanner.GenerateSpec(TTaskManagerService);
finally
oScanner.Free;
end;
oServer := TsgcHTTPServer.Create(nil);
oServer.Bindings.Add.Port := 8081;
oOpenAPI := TsgcWSAPIServer_OpenAPI.Create(nil);
oOpenAPI.LoadFromString(vSpec);
oOpenAPI.OnRequest := MyOnRequest;
oOpenAPI.Server := oServer;
oServer.Active := True;
end;
Les attributs couvrent les métadonnées courantes : sgcServiceContract remplit le bloc info d'OpenAPI, sgcRoute définit le chemin au niveau de la classe ou de la méthode, sgcHttpGet / Post / Put / Delete / Patch / Head / Options choisit le verbe, sgcSummary et sgcDescription documentent l'opération, sgcTag la regroupe dans Swagger UI, sgcResponse(code, description) déclare chaque réponse, et sgcFromPath / FromQuery / FromBody / FromHeader avec sgcRequired décrivent chaque paramètre.
Configuration — OpenAPIOptions
Toute la configuration côté serveur se trouve sous OpenAPIOptions sur le composant API, regroupée en cinq sous-options. Ces trois-ci portent les réglages courants :
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;
Avec la validation activée, chaque requête entrante est vérifiée par rapport aux schémas JSON déclarés dans la spécification avant d'atteindre votre gestionnaire — champs obligatoires, types, formats, énumérations, plages de valeurs. Les échecs déclenchent l'événement OnValidationError avec la liste des erreurs et un indicateur pour accepter ou rejeter la requête.
Événements
Six événements couvrent le cycle de vie de la requête :
OnBeforeRequest : se déclenche avant le dispatch ; définissez Accept := False pour rejeter avec un 403 Forbidden. Utile pour la limitation de débit, la journalisation ou les contrôles par route.
OnAuthenticate : se déclenche avant le gestionnaire principal ; définissez Authenticated := False pour rejeter avec 401 Unauthorized. Inspectez les en-têtes, les cookies ou les paramètres de requête pour décider.
OnValidationError : se déclenche lorsque la validation échoue ; reçoit la liste des erreurs. Définissez Continue := False pour rejeter avec 400 Bad Request.
OnRequest : l'événement principal de dispatch. Regardez aOperationId, écrivez la réponse dans aContext.Response, définissez Handled := True.
OnAfterRequest : se déclenche après le retour du gestionnaire — idéal pour les métriques ou la journalisation d'audit.
OnException : se déclenche si une exception non gérée remonte depuis votre gestionnaire. Ajustez aResponseCode si vous souhaitez autre chose que 500 Internal Server Error.
Les deux sous-options restantes ajoutent les leurs : Security pilote OnValidateAPIKey, OnValidateBasic et OnValidateBearer pour les securitySchemes déclarés par la spécification, et Mock répond à une opération sans gestionnaire à partir des propres exemples de la spécification.
Démos
Deux démos complètes sont livrées avec sgcOpenAPI 2026.6, toutes deux hébergées par la paire autonome, de sorte qu'aucune installation de sgcWebSockets n'est requise :
- Demos/30.Server/01.OpenAPI_Server_CodeFirst, une API Task Manager définie entièrement avec des attributs sur une classe Delphi.
- Demos/30.Server/02.OpenAPI_Server_SpecFirst, l'exemple classique Petstore, servi depuis
petstore.json.
Mise à niveau
Si vous utilisez actuellement TsgcWSServer_API_OpenAPI avec sgcWebSockets, rien ne change. La classe, ses propriétés et ses événements sont tous préservés, et l'implémentation délègue au moteur partagé. TsgcWSAPIServer_OpenAPI est le descendant publié de cette même classe, si bien que la seule chose que change sgcOpenAPI, c'est la provenance du package.
sgcOpenAPI 2026.6 sera disponible sur la page de téléchargements en juin.
Questions, retours ou aide à la migration ? Contactez-nous — vous obtiendrez une réponse des personnes qui ont écrit le code.
