Dans l'approche Spec-First, la spécification OpenAPI 3.0 (JSON ou YAML) est la source de vérité : elle décrit chaque chemin, opération, paramètre et schéma. Lorsque le serveur démarre, il analyse la spécification et construit la table de routage automatiquement ; vous n'avez qu'à fournir la logique métier pour chaque opération.
Ce workflow est celui recommandé lorsque le contrat de l'API existe déjà, lorsqu'il est partagé avec les consommateurs, ou lorsqu'il est maintenu en dehors du code Delphi.
Utilisez LoadFromFile pour charger la spécification depuis le disque, ou LoadFromString pour la charger depuis une chaîne en mémoire (par exemple, une spécification récupérée depuis une base de données ou générée à l'exécution).
uses sgcHTTPServer_OpenAPI;
var
oServer: TsgcHTTPServer_OpenAPI;
begin
oServer := TsgcHTTPServer_OpenAPI.Create(nil);
oServer.Bindings.Add.Port := 8080;
oServer.LoadFromFile('petstore.json');
oServer.OnRequest := MyOnRequest;
oServer.Active := True;
end;
Une fois chargée, la table de routage est construite à partir de la section paths de la spécification. Les segments de modèle tels que /pets/{petId} sont reconnus automatiquement et les valeurs capturées sont exposées via aContext.PathParamAsXxx.
Le serveur dispatche chaque requête entrante à l'événement OnRequest, en passant l'operationId déclaré dans la spécification. Utilisez une simple chaîne if/else (ou une recherche dans un dictionnaire) pour router l'opération vers le bon gestionnaire.
procedure TForm1.MyOnRequest(Sender: TObject; const aOperationId: string;
const aContext: TsgcOpenAPIServerContext; var Handled: Boolean);
begin
if aOperationId = 'listPets' then
DoListPets(aContext)
else if aOperationId = 'getPetById' then
DoGetPetById(aContext)
else if aOperationId = 'createPet' then
DoCreatePet(aContext)
else
aContext.RespondError(404, 'Not Found', 'Unknown operation');
Handled := True;
end;
L'objet TsgcOpenAPIServerContext expose des accesseurs typés pour chaque partie de la requête :
procedure TForm1.DoGetPetById(const aContext: TsgcOpenAPIServerContext);
var
vPetId: Integer;
vFields: string;
vBody: string;
begin
// path parameter declared as /pets/{petId}
vPetId := aContext.PathParamAsInteger('petId');
// optional query string ?fields=name,status
vFields := aContext.QueryParamAsString('fields', 'name');
// raw request body (when present)
vBody := aContext.BodyAsString;
end;
L'objet contexte fournit également des utilitaires pour écrire la réponse. Les plus courants sont RespondJSON et RespondError ; pour un contrôle total sur la réponse, définissez directement aContext.Response.Code et aContext.Response.ContentText.
// success: 200 with JSON body
aContext.RespondJSON(200, '{"id":1,"name":"Rex"}');
// error: 404 with title and detail
aContext.RespondError(404, 'Not Found', 'Pet not found');
// full control
aContext.Response.Code := 201;
aContext.Response.ContentType := 'application/json';
aContext.Response.ContentText := '{"id":42}';
Lorsque les indicateurs de validation sous OpenAPIOptions.Validation sont activés, le serveur valide chaque requête par rapport aux JSON-Schemas déclarés dans la spécification avant d'invoquer OnRequest :
ValidateRequestBody : le corps de la requête est vérifié par rapport au schéma référencé par requestBody de l'opération.
ValidateQueryParams : les paramètres de la chaîne de requête sont vérifiés par rapport à leurs schémas déclarés.
ValidatePathParams : les paramètres de chemin sont vérifiés par rapport à leurs schémas déclarés.
ValidateRequired : la requête est rejetée lorsqu'un paramètre déclaré comme obligatoire est manquant.
Lorsque la validation échoue, l'événement OnValidationError se déclenche avec la liste des erreurs. Définissez Continue sur False pour rejeter la requête avec une réponse 400, ou laissez-le à True pour laisser votre gestionnaire OnRequest décider.
oServer.OpenAPIOptions.Validation.ValidateRequest := True;
oServer.OpenAPIOptions.Validation.ValidateRequestBody := True;
oServer.OpenAPIOptions.Validation.ValidateRequired := True;
Un exemple spec-first complet est fourni sous Demos/30.Server/02.SpecFirst/.