A próxima versão do sgcOpenAPI — versão 2026.6, prevista para junho — traz um componente novo em folha: TsgcHTTPServer_OpenAPI. É um componente Delphi único e autocontido que hospeda um serviço OpenAPI 3.0 com um servidor HTTP embutido. Coloque-o em um formulário, aponte para uma especificação (ou gere uma a partir de uma classe Delphi com atributos RTTI), defina Active := True, e você tem uma API REST documentada com Swagger UI servido automaticamente.
A mudança principal é que o sgcOpenAPI não precisa mais do sgcWebSockets para hospedar um servidor HTTP. O novo componente é fornecido, empacotado e instalado inteiramente a partir do sgcOpenAPI. Se você já usa o sgcWebSockets, o componente anterior TsgcWSServer_API_OpenAPI continua funcionando sem alterações — ambos compartilham o mesmo motor internamente.
O que você obtém em um único componente
O TsgcHTTPServer_OpenAPI reúne três elementos:
- Um servidor HTTP embutido (baseado em Indy) com as propriedades habituais
Bindings,PorteActive. - O motor OpenAPI: análise de especificação, roteamento por modelo de caminho com segmentos
{paramName}, validação JSON-Schema, CORS, tratamento de exceções. - Dois endpoints servidos automaticamente: a especificação em
/openapi.jsone o Swagger UI em/docs. Ambos estão ativos por padrão e podem ser alternados emOpenAPIOptions.Endpoint.
Início rápido — o exemplo mínimo
Isto é tudo o que você precisa para hospedar um servidor OpenAPI funcional com 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;
Acesse http://localhost:8080/docs para o Swagger UI e http://localhost:8080/openapi.json para a especificação. Toda operação definida na especificação é roteada para o seu handler MyOnRequest com o operationId resolvido e um contexto de requisição totalmente construído.
Spec-First — carregue um arquivo OpenAPI 3.0 existente
Se você já tem um arquivo OpenAPI 3.0 em JSON ou YAML (Petstore, um contrato de API interno, um esquema público que deseja simular), o spec-first é a maneira mais rápida de servi-lo. LoadFromFile lê e analisa a especificação, constrói uma tabela de rotas a partir da seção paths e compara cada requisição recebida com ela.
O operationId de cada rota é a chave de despacho. Dentro de OnRequest você trata cada operação por vez:
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;
O TsgcOpenAPIServerContext fornece acessadores tipados para tudo o que está na requisição: PathParamAsString / PathParamAsInteger para segmentos baseados em modelo, QueryParamAsString / QueryParamAsInteger / QueryParamAsBoolean com valores padrão, BodyAsString / BodyAsJSON para o corpo da requisição, e HeaderValue para qualquer cabeçalho recebido. Para responder, use os helpers RespondJSON(code, content) e RespondError(code, title, detail), ou defina Response.Code, Response.ContentType e Response.Content diretamente para controle total.
Code-First — gere a especificação a partir de uma classe Delphi
Se você preferir escrever o contrato da API em Delphi e deixar a especificação ser gerada, decore uma classe com atributos RTTI. O TsgcOpenAPICodeFirstScanner percorre a classe, constrói um documento JSON OpenAPI 3.0 completo, e você carrega isso no servidor com LoadFromString. Isto requer Delphi XE7 ou mais recente (para RTTI estendido).
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;
Os corpos dos métodos são stubs — eles existem apenas para que o compilador emita RTTI para eles. O trabalho real acontece em OnRequest, despachado pelo operationId que o scanner deriva de cada nome de método (ListTasks, CreateTask, GetTask…).
Entregue a classe ao scanner na inicialização e carregue a especificação gerada no servidor:
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;
Os atributos cobrem os metadados comuns: sgcServiceContract preenche o bloco info do OpenAPI, sgcRoute define o caminho no nível da classe ou do método, sgcHttpGet / Post / Put / Delete / Patch / Head / Options escolhe o verbo, sgcSummary e sgcDescription documentam a operação, sgcTag a agrupa no Swagger UI, sgcResponse(code, description) declara cada resposta, e sgcFromPath / FromQuery / FromBody / FromHeader em conjunto com sgcRequired descrevem cada parâmetro.
Configuração — OpenAPIOptions
Toda a configuração do lado do servidor fica em OpenAPIOptions, agrupada em três subopções:
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;
Com a validação ativada, toda requisição recebida é checada em relação aos JSON Schemas declarados na especificação antes de chegar ao seu handler — campos obrigatórios, tipos, formatos, enums, intervalos. Falhas disparam o evento OnValidationError com a lista de erros e um flag para aceitar ou rejeitar a requisição.
Eventos
O componente expõe seis eventos para o ciclo de vida da requisição:
OnBeforeRequest: dispara antes do despacho; defina Accept := False para rejeitar com 403 Forbidden. Útil para limitação de taxa, registro de logs ou controles por rota.
OnAuthenticate: dispara antes do handler principal; defina Authenticated := False para rejeitar com 401 Unauthorized. Inspecione cabeçalhos, cookies ou parâmetros de consulta para decidir.
OnValidationError: dispara quando a validação falha; recebe a lista de erros. Defina Continue := False para rejeitar com 400 Bad Request.
OnRequest: o evento principal de despacho. Observe o aOperationId, escreva a resposta em aContext.Response, defina Handled := True.
OnAfterRequest: dispara depois que o handler retorna — ideal para métricas ou log de auditoria.
OnException: dispara se uma exceção não tratada surgir do seu handler. Ajuste aResponseCode se quiser algo diferente de 500 Internal Server Error.
Demos
Duas demos completas acompanham o sgcOpenAPI 2026.6, ambas usando apenas o novo componente independente — sem necessidade de instalação do sgcWebSockets:
- Demos/30.Server/01.CodeFirst — uma API Task Manager definida inteiramente com atributos em uma classe Delphi.
- Demos/30.Server/02.SpecFirst — o clássico exemplo Petstore, servido a partir de
petstore.json.
Atualização
Se você atualmente usa TsgcWSServer_API_OpenAPI com sgcWebSockets, nada muda — a classe, as propriedades e os eventos são todos preservados, e a implementação agora delega ao mesmo motor compartilhado que alimenta o novo componente independente. Você pode manter seu código existente como está, ou migrar um formulário por vez para TsgcHTTPServer_OpenAPI para eliminar a dependência do sgcWebSockets.
O sgcOpenAPI 2026.6 estará disponível na página de downloads em junho.
Dúvidas, feedback ou ajuda com a migração? Entre em contato — você receberá uma resposta das pessoas que escreveram o código.
