Delphi için OpenAPI Sunucusu: TsgcWSAPIServer_OpenAPI

· Bileşenler

sgcWebSockets Enterprise sürümü, bir OpenAPI 3 açıklamasını Delphi uygulamanızın içinde çalışan bir REST sunucusuna dönüştüren yeni bir bileşen, TsgcWSAPIServer_OpenAPI ile gelir. Onu bir forma bırakın, bir HTTP sunucusuna yönlendirin, ona bir spesifikasyon verin — ve rotalar, istek doğrulama, hata yanıtları ve canlı Swagger UI belgeleri sizin için bağlanır. Bu yazı, bileşenin nasıl çalıştığını, onu sürmenizin iki yolunu (spesifikasyon-önce ve kod-önce), önemli yapılandırma ayarlarını ve doğrudan yeni bir projeye yapıştırabileceğiniz tam bir Delphi örneğini adım adım anlatır.

Bileşen ne yapar

TsgcWSAPIServer_OpenAPI, mevcut API-sunucusu uzantı noktası aracılığıyla TsgcWebSocketHTTPServer'a bağlanan ince bir API sunucusudur. Onu bir sunucuya iliştirir, bir OpenAPI 3.0 spesifikasyonu yükler ve gelen her HTTP isteğinde dört şey yapar:

Sonuç, spesifikasyonun tek doğru kaynağı haline gelmesidir: JSON'da bir yol, bir parametre veya bir yanıt kodu değiştirin, yeniden başlatın ve sunucu Delphi kodunu yeniden derlemeden yeni sözleşmeyi alır.

Spesifikasyon-önce: mevcut bir OpenAPI 3 dosyası yükleyin

Zaten bir OpenAPI 3 belgeniz varsa (örneğin bir API tasarımcısından dışa aktarılmış bir petstore.json) bağlama esasen üç satırdır — bileşeni oluşturun, spesifikasyonu yükleyin, bir sunucu iliştirin. Geri kalan her şey yapılandırma ve gerçek yanıtları üreten OnRequest işleyicisidir.

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;

OnRequest olayı operationId başına gönderilir — YAML/JSON'da her işlemin yanına yazdığınız dize. İşlem başına bir dal yazar, girdileri bağlamdan okur ve bir yanıt yayarsınız:

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;

TsgcOpenAPIServerContext nesnesi, her işleyicinin işçi atıdır. Path ve query parametrelerini ada göre (PathParamAsString, PathParamAsInteger, QueryParamAsString, QueryParamAsInteger, QueryParamAsBoolean), HeaderValue aracılığıyla başlık aramasını, gövdeyi bir dize (BodyAsString) veya önceden ayrıştırılmış JSON (BodyAsJSON) olarak ve ayrıca iki yanıt yardımcısını açığa çıkarır: normal bir yük için RespondJSON(code, content) ve istemcilerin her zaman tutarlı bir hata biçimi alması için RFC 7807 tarzında bir application/problem+json gövdesi üreten RespondError(code, title, detail).

Kod-önce: spesifikasyonu Delphi öznitelilerinden oluşturun

İkinci mod ters akıştır: API'nizi öznitelilerle süslenmiş bir Delphi sınıfı olarak bildirir, tarayıcıdan çalışma zamanında OpenAPI belgesini yaymasını ister ve o belgeyi aynı bileşene geri beslersiniz. JSON'da elle yazılacak bir şey yoktur.

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;

Sınıfın kendisinin gerçek gövdelere ihtiyacı yoktur — tarayıcı onu RTTI aracılığıyla okur, gerçek mantık hâlâ OnRequest işleyicinizde bulunur. Spesifikasyonu oluşturmak ve sunucuyu başlatmak birkaç satırdır:

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;

Öznitelik seti yaygın durumları kapsar: yönlendirme (sgcHttpGet, sgcHttpPost, sgcHttpPut, sgcHttpDelete, sgcHttpPatch, sgcRoute), parametre bağlama (sgcFromPath, sgcFromQuery, sgcFromHeader, sgcFromBody), doğrulama (sgcRequired, sgcMinLength, sgcMaxLength, sgcRange, sgcPattern) ve belgeleme (sgcSummary, sgcDescription, sgcTag, sgcResponse).

Yapılandırma ayrıntılı olarak

OpenAPIOptions, hepsini Object Inspector'da görebilmeniz için üç kalıcı alt nesneye gruplandırılmıştır:

OnRequest'in ötesinde, dört olay daha boru hattına müdahale etmenize olanak tanır: OnBeforeRequest (kısa devre yapmak için Accept := False ayarlayın, hız sınırlama veya günlük kaydı için kullanışlı), OnAfterRequest (bir yanıt ürettikten sonra son işleme), OnAuthenticate (bir token veya oturumu kontrol ettikten sonra Authenticated := True ayarlayın) ve OnException (çerçeve hata gövdesini yazmadan önce HTTP durumunu değiştirmenize olanak tanıyan her şeyi yakalayan).

Kutudan çıkar çıkmaz Swagger UI

ServeSwaggerUI := True ile sunucu, spesifikasyonu BasePath + '/openapi.json''dan yükleyen bir Swagger UI sayfasını BasePath + '/docs''ta yayımlar. URL'yi bir tarayıcıda açın ve kendi çalışan sunucunuzdan beslenen standart dene-bunu deneyimini elde edin — ayrı bir belge derlemesi yok, statik dışa aktarma yok. CORS ile birleştirildiğinde, bu, bir arka ucu (backend) bir ön uç (frontend) ekibine veya API'nize karşı entegre olan bir ortağa teslim etmenin en hızlı yoludur.

Edinme

Bileşen, sgcWebSockets'in Enterprise sürümünün bir parçasıdır ve SGC OpenAPI palet sayfasında kayıtlıdır. İki tam demo — biri bir Petstore JSON kullanan spesifikasyon-önce, biri bir görev yöneticisi hizmeti kullanan kod-önce — Demos\23.OpenAPI içinde gelir. En son derlemeyi sgcWebSockets indirme sayfasından indirin.

Sorular, geri bildirim veya onu mevcut bir projeye bağlama konusunda yardım mı? Bize ulaşın — kodu yazan kişilerden bir yanıt alacaksınız.