sgcOpenAPIの次期リリース、6月に予定されているバージョン2026.6は、sgcWebSockets をインストールせずにホストできるOpenAPI 3.0サーバーを提供します。これを実現するのは 2 つのコンポーネントです。Indy ベースの HTTP サーバーであるTsgcHTTPServerと、それにアタッチする API コンポーネントであるTsgcWSAPIServer_OpenAPIです。API コンポーネントにスペックを指定し(または RTTI 属性を持つ Delphi クラスから生成し)、そのServerプロパティを割り当て、HTTP サーバーを起動すれば、Swagger UI が自動配信されるドキュメント付き REST API が完成します。
目玉となる変更点は、sgcOpenAPI が HTTP サーバーをホストするために sgcWebSockets を必要としなくなったことです。両方のコンポーネントは、sgcOpenAPI から完全に出荷、パッケージ化、インストールされます。すでに sgcWebSockets を使用している場合も、おなじみのTsgcWSServer_API_OpenAPIコンポーネントは変更なく引き続き動作します。同じクラスだからです。両方の製品が、同じエンジンからこれを構築しています。
得られるもの
このペアは 3 つの要素をもたらします:
- HTTP サーバー(Indy ベース)、
TsgcHTTPServer。通常のBindings、Port、Activeプロパティを備えています。 - OpenAPIエンジン: スペック解析、
{paramName}セグメントによるパステンプレートルーティング、JSON-Schemaバリデーション、CORS、例外処理。 - 2つの自動配信エンドポイント:
/openapi.jsonのスペックと/docsのSwagger UI。両方ともデフォルトで有効になっており、OpenAPIOptions.Endpointで切り替えできます。
クイックスタート — 最小限の例
Swagger UI を備えた動作する OpenAPI サーバーをホストするために必要なものは、これだけです。API コンポーネントにはActiveプロパティがないことに注意してください。Serverを割り当てることでアタッチされ、nilを割り当てるとデタッチされますが、その間も HTTP サーバーは動作し続けます。
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;
Swagger UIにはhttp://localhost:8080/docs、スペックにはhttp://localhost:8080/openapi.jsonにアクセスしてください。スペックで定義されたすべての操作は、解決されたoperationIdと完全に構築されたリクエストコンテキストを伴ってMyOnRequestハンドラーにルーティングされます。
スペックファースト — 既存のOpenAPI 3.0ファイルを読み込む
既存の OpenAPI 3.0 JSON ファイル(Petstore、社内 API コントラクト、モック化したい公開スキーマなど)がある場合、スペックファーストはそれを提供する最速の方法です。LoadFromFileはスペックを読み込んで解析し、pathsセクションからルートテーブルを構築し、受信したすべてのリクエストをそれと照合します。サーバーが読み込めるのは JSON だけなので、YAML のコントラクトはあらかじめ、たとえばsgcOpenAPI.exeで変換しておいてください。
各ルートのoperationIdがディスパッチキーになります。OnRequestの内部で、各操作を順番に処理します:
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はリクエストのすべてに型付きアクセサを提供します: テンプレート化されたセグメント用のPathParamAsString / PathParamAsInteger、デフォルト値付きのQueryParamAsString / QueryParamAsInteger / QueryParamAsBoolean、リクエストボディ用のBodyAsString / BodyAsJSON、受信ヘッダー用のHeaderValue。応答するには、ヘルパーRespondJSON(code, content)とRespondError(code, title, detail)を使うか、完全な制御のためにResponse.Code、Response.ContentType、Response.Contentを直接設定します。
コードファースト — Delphiクラスからスペックを生成する
DelphiでAPIコントラクトを記述してスペックを生成させたい場合は、クラスをRTTI属性で装飾します。TsgcOpenAPICodeFirstScannerがクラスを走査し、完全なOpenAPI 3.0 JSONドキュメントを構築するので、LoadFromStringでサーバーに読み込みます。これにはDelphi XE7以降が必要です(拡張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;
メソッド本体はスタブです — コンパイラがRTTIを生成するためだけに存在します。実際の処理は、スキャナーが各メソッド名から導出する operationId (ListTasks、CreateTask、GetTask…)によってディスパッチされるOnRequest内で行われます。
起動時にクラスをスキャナーに渡し、生成されたスペックをサーバーに読み込みます:
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;
属性は一般的なメタデータをカバーします: sgcServiceContractはOpenAPIのinfoブロックを設定し、sgcRouteはクラスまたはメソッドレベルでパスを設定し、sgcHttpGet / Post / Put / Delete / Patch / Head / Optionsは動詞を選択し、sgcSummaryとsgcDescriptionは操作をドキュメント化し、sgcTagはSwagger UIでグループ化し、sgcResponse(code, description)は各応答を宣言し、sgcFromPath / FromQuery / FromBody / FromHeaderはsgcRequiredと組み合わせて各パラメータを記述します。
設定 — OpenAPIOptions
すべてのサーバーサイド設定は、API コンポーネントのOpenAPIOptionsの下にあり、5 つのサブオプションにグループ化されています。このうち 3 つが日常的な設定を担います:
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;
バリデーションを有効にすると、受信したすべてのリクエストは、ハンドラーに到達する前に、スペックで宣言されたJSONスキーマに対してチェックされます — 必須フィールド、型、フォーマット、列挙、範囲。失敗するとエラー一覧とリクエストを受け入れるか拒否するかのフラグを伴ってOnValidationErrorイベントが発生します。
イベント
6 つのイベントがリクエストのライフサイクルをカバーします:
OnBeforeRequest: ディスパッチ前に発生します。Accept := Falseを設定すると403 Forbiddenで拒否されます。レート制限、ロギング、またはルートごとのゲートに便利です。
OnAuthenticate: メインハンドラーの前に発生します。Authenticated := Falseを設定すると401 Unauthorizedで拒否されます。ヘッダー、クッキー、またはクエリパラメータを検査して判断します。
OnValidationError: バリデーションが失敗したときに発生し、エラー一覧を受け取ります。Continue := Falseを設定すると400 Bad Requestで拒否されます。
OnRequest: メインディスパッチイベント。aOperationIdを見て、aContext.Responseに応答を書き込み、Handled := Trueを設定します。
OnAfterRequest: ハンドラーが戻った後に発生します — メトリクスや監査ロギングに最適です。
OnException: ハンドラーから処理されない例外が発生した場合に発生します。500 Internal Server Error以外を返したい場合はaResponseCodeを調整します。
残る 2 つのサブオプションにもそれぞれ役割があります。Securityは、スペックが宣言するsecuritySchemesに対してOnValidateAPIKey、OnValidateBasic、OnValidateBearerを駆動し、Mockはハンドラーのないオペレーションにスペック自身の例から応答します。
デモ
sgcOpenAPI 2026.6 には 2 つの完全なデモが同梱されており、どちらもスタンドアロンのペアでホストされるため、sgcWebSockets のインストールは不要です:
- Demos/30.Server/01.OpenAPI_Server_CodeFirst、Delphi クラスの属性のみで定義された Task Manager API。
- Demos/30.Server/02.OpenAPI_Server_SpecFirst、
petstore.jsonから提供される定番の Petstore の例。
アップグレード
現在 sgcWebSockets でTsgcWSServer_API_OpenAPIを使用している場合、何も変わりません。クラス、プロパティ、イベントはすべて保持され、実装は共有エンジンに委譲されます。TsgcWSAPIServer_OpenAPIは、その同じクラスを公開した子孫にあたるので、sgcOpenAPI が変えるのはパッケージの出所だけです。
sgcOpenAPI 2026.6は6月にダウンロードページで入手できるようになります。
ご質問、フィードバック、移行の支援が必要な場合 お問い合わせください — コードを書いた本人から返信があります。
