Kolejne wydanie sgcOpenAPI — wersja 2026.6, planowane na czerwiec — dostarcza zupełnie nowy komponent: TsgcHTTPServer_OpenAPI. To pojedynczy, samodzielny komponent Delphi, który hostuje usługę OpenAPI 3.0 z wbudowanym serwerem HTTP. Upuść go na formularzu, wskaż specyfikację (lub wygeneruj ją z klasy Delphi za pomocą atrybutów RTTI), ustaw Active := True, 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. Nowy komponent jest dostarczany, pakowany i instalowany w całości z sgcOpenAPI. Jeśli już korzystasz z sgcWebSockets, dotychczasowy komponent TsgcWSServer_API_OpenAPI nadal działa bez zmian — oba wewnętrznie współdzielą ten sam silnik.
Co otrzymujesz w jednym komponencie
TsgcHTTPServer_OpenAPI łączy trzy elementy:
- Wbudowany serwer HTTP (oparty na Indy) z typowymi właściwościami
Bindings,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:
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;
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 lub YAML (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.
Kluczem do dyspozytora jest operationId każdej trasy. Wewnątrz OnRequest obsługujesz po kolei każdą operację:
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;
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_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;
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 znajduje się pod OpenAPIOptions, pogrupowana w trzy podopcje:
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
Komponent udostępnia sześć zdarzeń dla cyklu ż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.
Dema
Dwa kompletne dema są dostarczane z sgcOpenAPI 2026.6, oba używające wyłącznie nowego, samodzielnego komponentu — bez konieczności instalacji sgcWebSockets:
- Demos/30.Server/01.CodeFirst — Task Manager API zdefiniowane w całości przy użyciu atrybutów na klasie Delphi.
- Demos/30.Server/02.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, właściwości i zdarzenia zostały zachowane, a implementacja deleguje teraz pracę do tego samego współdzielonego silnika, który napędza nowy samodzielny komponent. Możesz pozostawić swój istniejący kod bez zmian lub migrować po jednym formularzu na raz do TsgcHTTPServer_OpenAPI, aby porzucić zależność od sgcWebSockets.
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.
