Edycja sgcWebSockets Enterprise dostarcza nowy komponent, TsgcWSAPIServer_OpenAPI, który zamienia opis OpenAPI 3 w działający serwer REST wewnątrz Twojej aplikacji Delphi. Upuść go na formularzu, wskaż serwer HTTP, przekaż specyfikację — a trasy, walidacja żądań, odpowiedzi błędów i dokumentacja na żywo w Swagger UI zostaną podłączone za Ciebie. Ten wpis przeprowadza przez to, jak działa komponent, dwa sposoby jego sterowania (spec-first i code-first), istotne pokrętła konfiguracyjne oraz kompletny przykład w Delphi, który możesz wkleić bezpośrednio do nowego projektu.
Co robi komponent
TsgcWSAPIServer_OpenAPI to lekki serwer API, który włącza się do TsgcWebSocketHTTPServer przez istniejący punkt rozszerzenia dla serwerów API. Podpinasz go do serwera, ładujesz specyfikację OpenAPI 3.0, a on dla każdego przychodzącego żądania HTTP wykonuje cztery rzeczy:
- dopasowuje URL i metodę HTTP do tras zadeklarowanych w specyfikacji (w tym parametrów
{path}); - waliduje żądanie — pola wymagane, parametry zapytania, parametry ścieżki i ciało żądania — względem schematów ze specyfikacji;
- wywołuje zdarzenie
OnRequestz rozpoznanymoperationIdi w pełni wypełnionym obiektem kontekstu, dzięki czemu Twój kod musi napisać tylko logikę biznesową; - od razu udostępnia dwa wbudowane punkty końcowe — surową specyfikację pod
/openapi.jsoni interaktywne Swagger UI pod/docs— z opcjonalnym preflight CORS na każdej trasie.
Efekt jest taki, że specyfikacja staje się jedynym źródłem prawdy: zmień ścieżkę, parametr lub kod odpowiedzi w JSON-ie, uruchom ponownie i serwer podejmuje nowy kontrakt bez rekompilacji kodu Delphi.
Spec-first: załaduj istniejący plik OpenAPI 3
Jeśli masz już dokument OpenAPI 3 (na przykład petstore.json wyeksportowany z projektanta API), podłączenie sprowadza się w istocie do trzech linii — utwórz komponent, załaduj specyfikację, podłącz serwer. Cała reszta to konfiguracja i obsługa zdarzenia OnRequest, która produkuje faktyczne odpowiedzi.
uses
sgcWebSocket, sgcWebSocket_Classes,
sgcWebSocket_Server_API_OpenAPI,
sgcHTTP_OpenAPI_Server;
var
WSServer: TsgcWebSocketHTTPServer;
FOpenAPI: TsgcWSAPIServer_OpenAPI;
begin
WSServer := TsgcWebSocketHTTPServer.Create(nil);
WSServer.Port := 8080;
FOpenAPI := TsgcWSAPIServer_OpenAPI.Create(nil);
FOpenAPI.OnRequest := OnOpenAPIRequest;
FOpenAPI.OnBeforeRequest := OnOpenAPIBeforeRequest;
FOpenAPI.OnValidationError := OnOpenAPIValidationError;
// Configuration
FOpenAPI.OpenAPIOptions.Endpoint.ServeSpec := True;
FOpenAPI.OpenAPIOptions.Endpoint.ServeSwaggerUI := True;
FOpenAPI.OpenAPIOptions.CORS.Enabled := True;
FOpenAPI.OpenAPIOptions.Validation.ValidateRequest := True;
FOpenAPI.OpenAPIOptions.Validation.ValidateRequired := True;
FOpenAPI.OpenAPIOptions.Validation.ValidateRequestBody := True;
// Load spec and attach to server
FOpenAPI.LoadFromFile('petstore.json');
FOpenAPI.Server := WSServer;
WSServer.Active := True;
// Swagger UI: http://localhost:8080/docs
// Raw spec: http://localhost:8080/openapi.json
end;
Zdarzenie OnRequest jest dystrybuowane per operationId — ciąg, który zapisałeś obok każdej operacji w YAML/JSON. Piszesz jedną gałąź na operację, czytasz wejścia z kontekstu i emitujesz odpowiedź:
procedure TForm1.OnOpenAPIRequest(Sender: TObject;
const aOperationId: string; const aContext: TsgcOpenAPIServerContext;
var Handled: Boolean);
var
vId: Int64;
vLimit: Integer;
begin
Handled := True;
if aOperationId = 'listPets' then
begin
vLimit := aContext.QueryParamAsInteger('limit', 100);
aContext.RespondJSON(200, BuildPetsJSON(vLimit));
end
else if aOperationId = 'getPetById' then
begin
vId := aContext.PathParamAsInteger('petId');
if FindPet(vId) then
aContext.RespondJSON(200, PetAsJSON(vId))
else
aContext.RespondError(404, 'Not Found',
Format('Pet %d not found', [vId]));
end
else
Handled := False;
end;
Obiekt TsgcOpenAPIServerContext jest koniem roboczym każdego handlera. Udostępnia parametry ścieżki i zapytania po nazwie (PathParamAsString, PathParamAsInteger, QueryParamAsString, QueryParamAsInteger, QueryParamAsBoolean), odczyt nagłówków przez HeaderValue, ciało jako tekst (BodyAsString) lub wstępnie sparsowany JSON (BodyAsJSON), a także dwa pomocnicze metody odpowiedzi: RespondJSON(code, content) dla zwykłego ładunku oraz RespondError(code, title, detail), który wytwarza ciało w stylu RFC 7807 typu application/problem+json, dzięki czemu klienci zawsze otrzymują spójny kształt błędu.
Code-first: generuj specyfikację z atrybutów Delphi
Drugi tryb to przepływ odwrotny: deklarujesz swoje API jako klasę Delphi udekorowaną atrybutami, prosisz skaner o wyemitowanie dokumentu OpenAPI w czasie uruchomienia i przekazujesz ten dokument z powrotem do tego samego komponentu. Nie ma nic do napisania ręcznie w JSON.
uses
sgcHTTP_OpenAPI_Server_CodeFirst;
type
[sgcServiceContract('Task Manager API',
'A simple task manager', '1.0.0')]
[sgcRoute('/api/v1')]
TTaskService = class
public
[sgcHttpGet]
[sgcRoute('/tasks')]
[sgcSummary('List all tasks')]
[sgcResponse(200, 'A list of tasks')]
procedure ListTasks([sgcFromQuery] const status: string); virtual;
[sgcHttpGet]
[sgcRoute('/tasks/{taskId}')]
[sgcSummary('Get a task by ID')]
[sgcResponse(200, 'The requested task')]
[sgcResponse(404, 'Task not found')]
procedure GetTask([sgcFromPath][sgcRequired]
const taskId: Integer); virtual;
[sgcHttpPost]
[sgcRoute('/tasks')]
[sgcSummary('Create a new task')]
[sgcResponse(201, 'Task created')]
procedure CreateTask([sgcFromBody] const body: string); virtual;
end;
Sama klasa nie musi mieć rzeczywistych ciał metod — skaner czyta ją przez RTTI, a właściwa logika nadal żyje w Twoim handlerze OnRequest. Wygenerowanie specyfikacji i uruchomienie serwera to kilka linii:
var
oScanner: TsgcOpenAPICodeFirstScanner;
vSpec: string;
begin
oScanner := TsgcOpenAPICodeFirstScanner.Create;
try
vSpec := oScanner.GenerateSpec(TTaskService);
finally
oScanner.Free;
end;
FOpenAPI.LoadFromString(vSpec);
FOpenAPI.Server := WSServer;
WSServer.Active := True;
end;
Zestaw atrybutów pokrywa typowe przypadki: routing (sgcHttpGet, sgcHttpPost, sgcHttpPut, sgcHttpDelete, sgcHttpPatch, sgcRoute), wiązanie parametrów (sgcFromPath, sgcFromQuery, sgcFromHeader, sgcFromBody), walidację (sgcRequired, sgcMinLength, sgcMaxLength, sgcRange, sgcPattern) oraz dokumentację (sgcSummary, sgcDescription, sgcTag, sgcResponse).
Konfiguracja w szczegółach
OpenAPIOptions jest pogrupowany w trzy trwałe pod-obiekty, dzięki czemu możesz zobaczyć je wszystkie w Inspektorze Obiektów:
Endpoint—BasePathdodaje prefiks do każdej trasy oraz do wbudowanych punktów końcowych/openapi.jsoni/docs;SpecFilemoże być używany w czasie projektowania jako alternatywa dlaLoadFromFile;ServeSpeciServeSwaggerUIprzełączają dwa wbudowane punkty końcowe (oba domyślnie włączone).Validation— głównym przełącznikiem jestValidateRequest;ValidateRequired,ValidateQueryParams,ValidatePathParamsiValidateRequestBodypozwalają zawęzić to, co jest sprawdzane. Gdy walidacja się nie powiedzie, wywoływane jestOnValidationErrorz listą problemów i flagąContinue— ustaw ją naFalse, aby automatycznie odrzucić żądanie.CORS— ustawEnabled := True, a serwer odpowiada na preflightowe żądaniaOPTIONSdla każdej trasy, używającAllowOrigins,AllowHeadersiAllowMethodsjako polityki odpowiedzi.
Poza OnRequest cztery kolejne zdarzenia pozwalają wpiąć się w potok: OnBeforeRequest (ustaw Accept := False, aby zwolnić obwód, przydatne do ograniczania szybkości lub logowania), OnAfterRequest (post-przetwarzanie po wyprodukowaniu odpowiedzi), OnAuthenticate (ustaw Authenticated := True po sprawdzeniu tokenu lub sesji) oraz OnException (uniwersalny przechwytujący wszystko, który pozwala zmienić status HTTP zanim framework zapisze ciało błędu).
Swagger UI od razu po wyjęciu z pudełka
Przy ServeSwaggerUI := True serwer publikuje stronę Swagger UI pod BasePath + '/docs', która ładuje specyfikację z BasePath + '/openapi.json'. Otwórz URL w przeglądarce i otrzymasz standardowe doświadczenie try-it-out, zasilane z Twojego własnego działającego serwera — bez osobnego budowania dokumentacji, bez statycznego eksportu. W połączeniu z CORS jest to najszybszy sposób na przekazanie backendu zespołowi frontendowemu lub partnerowi integrującemu się z Twoim API.
Jak go zdobyć
Komponent jest częścią edycji Enterprise sgcWebSockets, zarejestrowanym na stronie palety SGC OpenAPI. Dwa kompletne dema — jedno spec-first wykorzystujące JSON Petstore, jedno code-first wykorzystujące usługę menedżera zadań — są dostarczane w Demos\23.OpenAPI. Pobierz najnowszą kompilację ze strony pobierania sgcWebSockets.
Pytania, opinie lub pomoc w podłączeniu komponentu do istniejącego projektu? Skontaktuj się z nami — otrzymasz odpowiedź od osób, które napisały kod.
