Kolejne wydanie sgcOpenAPI, wersja 2026.6, planowane na czerwiec, dostarcza serwer OpenAPI 3.0, który możesz hostować bez instalowania sgcWebSockets. Realizują to dwa komponenty: TsgcHTTPServer, serwer HTTP oparty na Indy, oraz TsgcWSAPIServer_OpenAPI, komponent API, który do niego podłączasz. Wskaż komponentowi API specyfikację (lub wygeneruj ją z klasy Delphi za pomocą atrybutów RTTI), przypisz jego właściwość Server, uruchom serwer HTTP, a otrzymasz udokumentowany REST API z automatycznie serwowanym Swagger UI.
Najważniejszą zmianą jest to, że sgcOpenAPI nie potrzebuje już sgcWebSockets do hostowania serwera HTTP. Oba komponenty są dostarczane, pakowane i instalowane w całości z sgcOpenAPI. Jeśli już korzystasz z sgcWebSockets, znany ci komponent TsgcWSServer_API_OpenAPI nadal działa bez zmian, ponieważ jest to ta sama klasa: oba produkty budują go z tego samego silnika.
Co otrzymujesz
Ta para zapewnia trzy elementy:
- Serwer HTTP (oparty na Indy),
TsgcHTTPServer, z typowymi właściwościamiBindings,PortiActive. - Silnik OpenAPI: parsowanie specyfikacji, routing oparty na szablonach ścieżek z segmentami
{paramName}, walidacja JSON-Schema, CORS, obsługa wyjątków. - Dwa automatycznie serwowane punkty końcowe: specyfikacja pod
/openapi.jsonoraz Swagger UI pod/docs. Oba są domyślnie włączone i można je przełączać wOpenAPIOptions.Endpoint.
Szybki start — minimalny przykład
To wszystko, czego potrzebujesz, aby uruchomić działający serwer OpenAPI ze Swagger UI. Zauważ, że komponent API nie ma własnej właściwości Active: przypisanie Server podłącza go, a przypisanie nil odłącza, podczas gdy serwer HTTP nadal działa.
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;
Przejdź do http://localhost:8080/docs, aby zobaczyć Swagger UI, oraz do http://localhost:8080/openapi.json, aby zobaczyć specyfikację. Każda operacja zdefiniowana w specyfikacji jest kierowana do twojej procedury obsługi MyOnRequest wraz z rozwiązanym operationId oraz w pełni zbudowanym kontekstem żądania.
Spec-First — wczytaj istniejący plik OpenAPI 3.0
Jeśli masz już plik OpenAPI 3.0 w formacie JSON (Petstore, wewnętrzny kontrakt API, publiczny schemat, który chcesz zasymulować), podejście spec-first jest najszybszym sposobem na jego udostępnienie. LoadFromFile wczytuje i parsuje specyfikację, buduje tablicę tras na podstawie sekcji paths i dopasowuje do niej każde przychodzące żądanie. Serwer czyta JSON, więc najpierw przekonwertuj kontrakt YAML, na przykład za pomocą sgcOpenAPI.exe.
Kluczem do dyspozytora jest operationId każdej trasy. Wewnątrz OnRequest obsługujesz po kolei każdą operację:
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;
TsgcOpenAPIServerContext udostępnia typowane akcesory do wszystkiego w żądaniu: PathParamAsString / PathParamAsInteger dla szablonowych segmentów, QueryParamAsString / QueryParamAsInteger / QueryParamAsBoolean z wartościami domyślnymi, BodyAsString / BodyAsJSON dla treści żądania oraz HeaderValue dla dowolnego przychodzącego nagłówka. Aby odpowiedzieć, użyj pomocników RespondJSON(code, content) i RespondError(code, title, detail), lub ustaw Response.Code, Response.ContentType i Response.Content bezpośrednio, aby uzyskać pełną kontrolę.
Code-First — wygeneruj specyfikację z klasy Delphi
Jeśli wolisz napisać kontrakt API w Delphi i pozwolić, aby specyfikacja została wygenerowana, udekoruj klasę atrybutami RTTI. TsgcOpenAPICodeFirstScanner przechodzi przez klasę, buduje kompletny dokument JSON OpenAPI 3.0, a Ty wczytujesz go do serwera za pomocą LoadFromString. Wymaga to Delphi XE7 lub nowszego (dla rozszerzonego 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;
Treści metod są zaślepkami — istnieją tylko po to, aby kompilator wyemitował dla nich RTTI. Właściwa praca odbywa się w OnRequest, dyspozycjonowana przez operationId, który skaner wyprowadza z każdej nazwy metody (ListTasks, CreateTask, GetTask…).
Przekaż klasę do skanera podczas uruchamiania i wczytaj wygenerowaną specyfikację do serwera:
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;
Atrybuty obejmują typowe metadane: sgcServiceContract wypełnia blok info w OpenAPI, sgcRoute ustawia ścieżkę na poziomie klasy lub metody, sgcHttpGet / Post / Put / Delete / Patch / Head / Options wybiera czasownik HTTP, sgcSummary i sgcDescription dokumentują operację, sgcTag grupuje ją w Swagger UI, sgcResponse(code, description) deklaruje każdą odpowiedź, a sgcFromPath / FromQuery / FromBody / FromHeader razem z sgcRequired opisują każdy parametr.
Konfiguracja — OpenAPIOptions
Cała konfiguracja po stronie serwera na komponencie API znajduje się pod OpenAPIOptions, pogrupowana w pięć podopcji. Te trzy zawierają ustawienia używane na co dzień:
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;
Przy włączonej walidacji każde przychodzące żądanie jest sprawdzane względem schematów JSON Schema zadeklarowanych w specyfikacji, zanim dotrze do twojej procedury obsługi — wymagane pola, typy, formaty, wyliczenia, zakresy. Niepowodzenia wywołują zdarzenie OnValidationError z listą błędów oraz flagą do akceptacji lub odrzucenia żądania.
Zdarzenia
Sześć zdarzeń obsługuje cykl życia żądania:
OnBeforeRequest: wywoływane przed dyspozytorem; ustaw Accept := False, aby odrzucić z kodem 403 Forbidden. Przydatne dla limitowania częstotliwości, logowania lub bramek na poziomie trasy.
OnAuthenticate: wywoływane przed główną procedurą obsługi; ustaw Authenticated := False, aby odrzucić z kodem 401 Unauthorized. Sprawdź nagłówki, cookies lub parametry zapytania, aby podjąć decyzję.
OnValidationError: wywoływane, gdy walidacja się nie powiedzie; odbiera listę błędów. Ustaw Continue := False, aby odrzucić z kodem 400 Bad Request.
OnRequest: główne zdarzenie dyspozytora. Spójrz na aOperationId, zapisz odpowiedź do aContext.Response, ustaw Handled := True.
OnAfterRequest: wywoływane po zakończeniu procedury obsługi — idealne dla metryk lub logowania audytu.
OnException: wywoływane, jeśli z procedury obsługi wycieknie nieobsłużony wyjątek. Dostosuj aResponseCode, jeśli chcesz coś innego niż 500 Internal Server Error.
Pozostałe dwa podopcje dodają własne funkcje: Security obsługuje OnValidateAPIKey, OnValidateBasic i OnValidateBearer dla securitySchemes zadeklarowanych w specyfikacji, a Mock odpowiada na operację bez procedury obsługi na podstawie przykładów z samej specyfikacji.
Dema
Dwa kompletne dema są dostarczane z sgcOpenAPI 2026.6, oba hostowane przez tę samodzielną parę, więc instalacja sgcWebSockets nie jest wymagana:
- Demos/30.Server/01.OpenAPI_Server_CodeFirst, Task Manager API zdefiniowane w całości przy użyciu atrybutów na klasie Delphi.
- Demos/30.Server/02.OpenAPI_Server_SpecFirst, klasyczny przykład Petstore, serwowany z pliku
petstore.json.
Aktualizacja
Jeśli obecnie używasz TsgcWSServer_API_OpenAPI wraz z sgcWebSockets, nic się nie zmienia. Klasa, jej właściwości i zdarzenia są w pełni zachowane, a implementacja deleguje pracę do tego samego współdzielonego silnika. TsgcWSAPIServer_OpenAPI jest publikowanym potomkiem tej samej klasy, więc jedyne, co zmienia sgcOpenAPI, to skąd pochodzi pakiet.
sgcOpenAPI 2026.6 będzie dostępne na stronie pobierania w czerwcu.
Masz pytania, opinie lub potrzebujesz pomocy z migracją? Skontaktuj się z nami — otrzymasz odpowiedź od osób, które napisały kod.
