Serwer OpenAPI dla Delphi

TsgcWSAPIServer_OpenAPI serwuje dokument OpenAPI 3.x, który wczytasz, dopasowuje do niego każde przychodzące żądanie, waliduje żądanie zanim uruchomi się Twój handler, i publikuje dokument oraz stronę Swagger UI z tego samego portu. Jeden komponent Delphi, podpięty do TsgcHTTPServer.

OpenAPI 3.0 i 3.1
HTTP/2 + TLS 1.3
Swagger UI pod /docs
Spec-first lub Code-first

TsgcWSAPIServer_OpenAPI

Jeden komponent Delphi, który zamienia dokument OpenAPI w działający, walidowany, samodokumentujący się serwer REST.

Klasa komponentu

TsgcWSAPIServer_OpenAPI, zadeklarowana w sgcWebSocket_Server_API_OpenAPI

Serwer hostujący

Przypisz właściwości Server obiekt TsgcHTTPServer, TsgcHTTPRESTServer lub TsgcWebSocketHTTPServer. Host odpowiada za port, bindingi i TLS.

Format spec

Dokumenty OpenAPI 3.0 i 3.1, wczytywane jako JSON przez LoadFromFile i LoadFromString

Dwa podejścia

Spec-first z dokumentu, który już masz, albo code-first z klasy Delphi oznaczonej atrybutami. Code-first wymaga Delphi XE7 lub nowszego.

Edycja

Dostarczany z sgcOpenAPI. W sgcWebSockets należy do edycji Enterprise, na stronie palety SGC OpenAPI.

Wbudowane endpointy

/openapi.json dla dokumentu i /docs dla Swagger UI, oba włączone domyślnie w OpenAPIOptions.Endpoint

Spec-first lub Code-first, Ty wybierasz

Ten sam komponent działa w obu trybach. Zacznij od kontraktu JSON albo opisz API w Delphi i pozwól skanerowi wygenerować dokument za Ciebie.

1. Spec-first

Załaduj petstore.json przez LoadFromFile, rozdzielaj po operation id wewnątrz OnRequest i zacznij serwować. Routing, binding parametrów ścieżki i zapytania oraz walidacja pochodzą wprost z kontraktu, więc piszesz tylko logikę biznesową.

Najlepsze dla: zespołów ze wspólnym kontraktem projektowym, integracji API-led lub poliglotycznych back-endów, w których spec jest źródłem prawdy.

2. Code-first

Oznacz zwykłą klasę Delphi atrybutami sgcServiceContract, sgcRoute, sgcHttpGet oraz atrybutami parametrów sgcFromPath / sgcFromQuery / sgcFromBody. TsgcOpenAPICodeFirstScanner.GenerateSpec buduje dokument OpenAPI z RTTI klasy, Ty przekazujesz go do LoadFromString, a ten sam endpoint /openapi.json go publikuje.

Najlepsze dla: szybkiego prototypowania, usług wewnętrznych lub przenoszenia istniejącej powierzchni REST TIdHTTPServer / DataSnap do samodokumentującego się API.

Działający serwer w 20 linijkach

Utwórz komponent, wczytaj dokument, podłącz go do serwera HTTP. To cała konfiguracja.

Delphi
uses
  sgcHTTP_Server, sgcHTTP_OpenAPI_Server, sgcWebSocket_Server_API_OpenAPI;

procedure TForm1.FormCreate(Sender: TObject);
begin
  FServer := TsgcHTTPServer.Create(Self);
  FServer.Port := 8080;

  FOpenAPI := TsgcWSAPIServer_OpenAPI.Create(Self);
  FOpenAPI.LoadFromFile('petstore.json');      // any OpenAPI 3.x document
  FOpenAPI.OpenAPIOptions.Endpoint.ServeSpec := True;
  FOpenAPI.OpenAPIOptions.Endpoint.ServeSwaggerUI := True;
  FOpenAPI.OnRequest := OpenAPIRequest;
  FOpenAPI.Server := FServer;                // Server is the switch, there is no Active

  FServer.Active := True;
end;

// one event, dispatched by operation id
procedure TForm1.OpenAPIRequest(Sender: TObject;
  const aOperationId: string;
  const aContext: TsgcOpenAPIServerContext;
  var Handled: Boolean);
begin
  Handled := True;
  if aOperationId = 'getPetById' then
    aContext.RespondJSON(200, FPets.Values[aContext.PathParamAsString('petId')])
  else
    Handled := False;
end;

Co dostajesz od razu z pudełka: GET /pets/{petId} trafia do powyższego handlera z aOperationId ustawionym na getPetById, GET /openapi.json zwraca wczytany dokument, GET /docs otwiera Swagger UI. OpenAPIOptions.Endpoint.BasePath przenosi całą powierzchnię pod wybrany prefiks, a TLS i HTTP/2 pochodzą z serwera hostującego.

Parametry zadeklarowane w dokumencie OpenAPI są odczytywane i konwertowane przez jeden typowany kontekst. Przy włączonej walidacji nieprawidłowy typ jest odrzucany odpowiedzią 400 Bad Request, zanim uruchomi się Twój handler.

Delphi
// spec snippet
//   /pets:
//     get:
//       operationId: listPets
//       parameters:
//         - name: limit       in: query    schema: { type: integer, maximum: 100 }
//         - name: status      in: query    schema: { type: string, enum: [available, pending, sold] }
//         - name: X-Tenant-Id in: header   required: true

procedure TForm1.HandleListPets(const aContext: TsgcOpenAPIServerContext);
var
  vLimit:  Integer;
  vStatus: string;
  vTenant: string;
begin
  vLimit  := aContext.QueryParamAsInteger('limit', 20);        // default 20
  vStatus := aContext.QueryParamAsString ('status', 'available');
  vTenant := aContext.HeaderValue        ('X-Tenant-Id');   // required in the spec

  aContext.RespondJSON(200, PetRepo.List(vTenant, vStatus, vLimit));
end;

Walidacja schematu, zanim uruchomi się Twój handler

Każde przychodzące żądanie jest sprawdzane względem schematów zadeklarowanych w dokumencie. Błąd jest zwracany jako dokument problemu w stylu RFC 7807 z listą wszystkich błędów i nigdy nie dociera do Twojego handlera, chyba że sam na to pozwolisz.

Co jest sprawdzane

type, required, properties i additionalProperties, enum i const, minLength / maxLength, pattern, minimum / maximum wraz z ich formami wyłącznymi, multipleOf, items, minItems / maxItems, uniqueItems, nullable, not oraz oneOf / anyOf / allOf. Słowo kluczowe format jest egzekwowane dla date, date-time, email, ipv4, uri i uuid.

Wybierz zakres

Validation.ValidateRequest to główny przełącznik i sam w sobie waliduje każdy zakres. Zawęź go przez ValidateRequestBody, ValidateQueryParams, ValidatePathParams, ValidateHeaderParams i ValidateCookieParams. EnforceRequired działa niezależnie od wybranego zakresu.

Ostatnie słowo należy do Ciebie

OnValidationError przekazuje Ci identyfikator operacji i pełną listę błędów. Jego flaga Continue przychodzi jako False, więc żądanie jest odrzucane, chyba że świadomie ustawisz ją na True. Po wczytaniu Validation.Warnings wymienia każde słowo kluczowe schematu użyte w dokumencie, które nie jest egzekwowane, więc pusta lista oznacza, że nic nie zostało pominięte.

JSON, odpowiedź 400 zapisywana przez silnik
{
  "type":   "about:blank",
  "title":  "Bad Request",
  "status": 400,
  "detail": "Request validation failed",
  "errors": [
    "/email: invalid email format",
    "/age: must be <= 120",
    "/status: value not in enum"
  ]
}

Schematy auth sterowane specyfikacją

Ustaw Security.EnforceSecurity, a securitySchemes zadeklarowane w dokumencie zaczną być stosowane do przychodzących żądań. Ty piszesz wyszukiwanie poświadczeń, komponent parsuje żądanie i odpowiada 401 lub 403, gdy wyszukiwanie mówi nie.

Klucz API

Odczytywany z nagłówka, parametru zapytania lub ciasteczka, zależnie od tego, co deklaruje schemat. OnValidateAPIKey otrzymuje schemat, nazwę, lokalizację i klucz, i odpowiada przez Valid.

HTTP Basic

Nagłówek Authorization jest parsowany za Ciebie. OnValidateBasic otrzymuje użytkownika i hasło i odpowiada przez Valid. Poświadczenia nigdy nie trafiają do logów.

Bearer i JWT

Security.JWTSecret weryfikuje token. Sekret HMAC jest używany tak, jak jest, a wartość zawierająca -----BEGIN jest traktowana jako klucz publiczny PEM. ValidateExpiration, Issuer i Audience sprawdzają roszczenia.

Własny weryfikator

Pozostaw JWTSecret puste, a token jest tylko sprawdzany pod kątem obecności, dzięki czemu OnValidateBearer może przekazać go do Twojej usługi tokenów i odpowiedzieć przez Valid.

401 lub 403

Żądanie, które zawiedzie, otrzymuje odpowiedź 401, albo 403, gdy uwierzytelnienie się powiodło, ale zabrakło zakresu. OnAuthenticate uruchamia się jako pierwsze i odrzuca kodem 401 w chwili, gdy wyczyścisz Authenticated.

Mock, zanim powstanie kod

Mock.Enabled odpowiada na operację bez handlera na podstawie własnych przykładów i schematów dokumentu, z kodem Mock.StatusCode, dzięki czemu zespół frontendu może pracować, zanim powstanie implementacja.

Delphi, token bearer weryfikowany przez Twój własny kod
FOpenAPI.OpenAPIOptions.Security.EnforceSecurity := True;
FOpenAPI.OpenAPIOptions.Security.JWTSecret := GetSecretFromEnvironment;
FOpenAPI.OpenAPIOptions.Security.ValidateExpiration := True;
FOpenAPI.OpenAPIOptions.Security.Issuer   := 'https://auth.example.com';
FOpenAPI.OpenAPIOptions.Security.Audience := 'api.example.com';
FOpenAPI.OnValidateBearer := OpenAPIValidateBearer;

procedure TForm1.OpenAPIValidateBearer(Sender: TObject;
  const aToken: string;
  const aContext: TsgcOpenAPIServerContext; var Valid: Boolean);
begin
  Valid := MyTokenService.Verify(aToken);
end;

Wbudowane Swagger UI

Bez zewnętrznej zależności, bez Node.js, bez budowania dokumentacji w pipeline'ie wdrożenia. Komponent sam generuje stronę i czyta dokument, który Twój serwer faktycznie serwuje.

/openapi.json

Wczytany przez Ciebie dokument, serwowany, gdy Endpoint.ServeSpec jest włączony. Zawsze zgodny z tym, co serwer faktycznie routuje. Wskaż na ten URL dowolny generator klientów, w tym sgcOpenAPI.

/docs

Interaktywna strona Swagger UI, serwowana, gdy Endpoint.ServeSwaggerUI jest włączony. Wypróbuj operacje, przeglądaj schematy, czytaj przykłady, wszystko zasilane przez Twój własny działający serwer.

Wersja przypięta albo w pełni offline

Strona domyślnie wczytuje swój CSS i JavaScript z publicznego CDN. Endpoint.SwaggerUIBaseURL przypina wersję, a Endpoint.SwaggerUIAssetsPath serwuje swagger-ui.css i swagger-ui-bundle.js z lokalnego folderu, więc działa też na maszynie odciętej od sieci.

Wszystko mieszka pod OpenAPIOptions

Pięć trwałych pod-obiektów, wszystkie widoczne w Inspektorze Obiektów, wszystkie przypisywalne w czasie działania.

Endpoint

BasePath dodaje prefiks do każdej trasy i obu wbudowanych endpointów. ServeSpec i ServeSwaggerUI je przełączają. SpecFile jest wczytywany leniwie, przy pierwszym żądaniu, które nie trafia w żaden z tych dwóch, więc użyj LoadFromFile, gdy dokument musi być kompletny od samego pierwszego wywołania.

Validation

ValidateRequest plus pięć przełączników zakresu oraz EnforceRequired. Warnings raportuje, po każdym wczytaniu, słowa kluczowe schematu użyte w dokumencie, których ten walidator nie egzekwuje.

CORS

Enabled, AllowOrigins, AllowHeaders i AllowMethods. Silnik znakuje odpowiedzi na ścieżkach należących do jego dokumentu, więc nadaj serwerowi hostującemu te same wartości dla ścieżek, które należą do niego.

Security

EnforceSecurity, JWTSecret, ValidateExpiration, Issuer i Audience. Wszystko, czego wbudowane sprawdzenia nie potrafią rozstrzygnąć, trafia do OnValidateAPIKey, OnValidateBasic lub OnValidateBearer.

Mock

Enabled i StatusCode. Operacja bez handlera otrzymuje odpowiedź na podstawie własnych przykładów i schematów dokumentu, dzięki czemu kontrakt jest wywoływalny, zanim powstanie implementacja.

Not Implemented, celowo

Pozostaw Handled na False, a silnik odpowie 501 Not Implemented, wskazując operację z nazwy, zamiast 404, które wygląda jak pomyłka w routingu.

Jeden serwer HTTP, wiele powierzchni

TsgcWSAPIServer_OpenAPI podpina się do tego samego serwera HTTP sgcWebSockets, który hostuje Twoje endpointy WebSocket, strumienie AI/LLM i pliki statyczne. Jeden port, jeden certyfikat TLS, jeden strumień logów.

Server to przełącznik

Nie ma właściwości Active. Przypisanie Server podłącza komponent, ustawienie go na nil odłącza go, w obu przypadkach podczas gdy serwer hostujący nadal działa. Po odłączeniu ścieżki należące do jego dokumentu trafiają wprost do Twojego zwykłego handlera.

Nigdy nie przejmuje serwera

Każde żądanie trafia najpierw do komponentu, a on odpowiada tylko na ścieżki zadeklarowane w jego dokumencie. Wszystko inne trafia do OnCommandGet jak dotychczas, więc sekcja oparta na kontrakcie żyje obok ręcznie pisanych tras i statycznej zawartości z DocumentRoot, wszystko na jednym porcie.

TLS i HTTP/2 serwera hostującego

Port, bindingi, certyfikat i negocjacja HTTP/2 należą do serwera hostującego, więc powierzchnia REST dziedziczy je bez zmian. Podłącz go do TsgcHTTPRESTServer, a CORS, metryki, health i wielodostępność tego serwera również zaczną obowiązywać.

Typowe wdrożenia

Publiczne API REST

Wersjonowane, kontraktowo testowane, z autogenerowanymi SDK, które Twoi klienci mogą pobrać z /openapi.json.

Wewnętrzne mikroserwisy

Kontrakty serwis-do-serwisu, które przeżywają refaktory — spec to test integracyjny.

Bramy przemysłowe / IoT

Urządzenia edge wystawiające udokumentowany REST control plane plus powierzchnię telemetrii MQTT lub WebSocket z tej samej binarki Delphi.

Odbiorniki webhooków

Payload webhooka każdego providera staje się typowanym rekordem Pascal — Stripe, GitHub, Twilio, Slack — z walidacją i idempotencją w komplecie.

Modernizacja legacy

Owiń stary back-end DataSnap lub RemObjects czystą powierzchnią OpenAPI bez przepisywania logiki biznesowej.

BFF (Backend-for-Frontend)

Zagreguj dwa lub trzy upstreamowe API za jedną specyfikacją w kształcie konsumenta — Twoja SPA lub aplikacja mobilna rozmawia z jednym, typowanym endpointem.

Łączy się z

OpenAPI Parser

Załaduj dowolną zewnętrzną spec do tego samego modelu, którego używa serwer — ta sama walidacja, ten sam system typów, te same prymitywy bezpieczeństwa.

Gotowe SDK do chmury

Ponad 1195 wygenerowanych SDK dla AWS, Azure, GCP, Stripe, GitHub, Kubernetes i innych — Twój serwer może wywoływać każde z nich z tej samej rodziny komponentów.

sgcWebSockets

WebSocket, MQTT, AMQP, WebRTC, AI/LLM, IoT — wszystko, co serwer HTTP może hostować obok Twojej powierzchni REST.

sgcSign

Podpisuj ciała żądań i odpowiedzi z XAdES / PAdES / CAdES dla branż regulowanych — integralność klasy eIDAS na każdej operacji.

Najkorzystniejsza oferta: All-AccessWszystkie produkty eSeGeCe, ze wsparciem Premium w cenie, już od €1,059 rocznie.
Zobacz cennik All-Access

Zbuduj swój pierwszy serwer OpenAPI w kilka minut

Pobierz darmową wersję próbną. Pełny serwer, oba UI, każdy schemat auth — bez limitów funkcji, bez bomby czasowej podczas ewaluacji.