Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Catalog · How the catalog works

Random project

APIFactory

Camada de integração para consumo de APIs REST em sistemas legados Delphi, desenvolvida com Object Pascal e bibliotecas nativas, com foco em padronização, reutilização e redução de complexidade.

View on GitHub

Anyone may press Interesting, signed in or not. It helps others find this project.

Member rating

No ratings yet.

Sign in to rate this project.

README

API Factory para Delphi

Integração com APIs REST em sistemas legados

Uma camada de abstração desenvolvida em Delphi para simplificar, padronizar e centralizar o consumo de APIs REST em aplicações legadas.

O projeto foi desenvolvido como parte de um Trabalho de Conclusão de Curso (TCC) e posteriormente aplicado em um cenário real de integração entre um sistema legado Delphi e uma API REST.


📌 Sobre o projeto

Integrações com APIs REST em sistemas legados Delphi podem envolver uma quantidade significativa de código relacionado à infraestrutura da comunicação HTTP.

Além da regra de negócio, é comum que o código responsável pela integração também precise lidar diretamente com:

  • criação e configuração do cliente HTTP;
  • configuração de headers;
  • autenticação;
  • serialização de objetos para JSON;
  • criação do corpo da requisição;
  • execução de requisições HTTP;
  • leitura da resposta;
  • desserialização do JSON;
  • tratamento de erros e exceções;
  • gerenciamento e liberação de recursos.

A proposta deste projeto é encapsular essas responsabilidades em uma API Factory, permitindo que o código consumidor se concentre principalmente na configuração da requisição e no tratamento do resultado.

Conceito

text
Aplicação Delphi
       │
       ▼
   API Factory
       │
       ├── HTTP Client
       ├── Headers
       ├── Autenticação
       ├── JSON
       ├── Tratamento de erros
       └── Gerenciamento de recursos
       │
       ▼
     API REST

🎯 Objetivos

A API Factory foi desenvolvida com os seguintes objetivos:

  • reduzir código repetitivo em integrações REST;
  • centralizar responsabilidades relacionadas à comunicação HTTP;
  • diminuir o acoplamento entre a regra de negócio e a infraestrutura HTTP;
  • padronizar a construção das requisições;
  • facilitar a serialização e desserialização de dados;
  • simplificar o tratamento das respostas;
  • facilitar a manutenção de integrações em sistemas legados.

🛠 Tecnologias utilizadas

  • Delphi 12 Community Edition
  • Object Pascal
  • System.Net.HttpClient
  • System.JSON
  • System.SysUtils
  • System.Classes

⚠️ O projeto não depende de frameworks externos para realizar as requisições HTTP. A implementação utiliza recursos disponíveis na própria plataforma Delphi.


⚙️ Funcionalidades

A API Factory disponibiliza uma interface fluente para construção das requisições.

Entre as funcionalidades estão:

  • Requisições GET
  • Requisições POST
  • Requisições PUT
  • Requisições DELETE
  • Configuração de URL base
  • Configuração de recursos/endpoints
  • Adição de headers
  • Autenticação
  • Envio de objetos como JSON
  • Conversão automática de JSON para objetos
  • Conversão automática de arrays
  • Retorno RAW
  • Tratamento de respostas
  • Tratamento de erros e exceções

🚀 Exemplos de utilização

📥 GET — Retorno RAW

A resposta pode ser obtida diretamente como uma string.

delphi
var
  Resp: string;
begin
  Resp :=
    TApiFactory.New
      .BaseURL('https://viacep.com.br')
      .Resource('/ws/01001000/json/')
      .Get
      .Raw;

  ShowMessage(Resp);
end;

📥 GET — Conversão automática para classe

A resposta JSON pode ser convertida automaticamente para uma classe utilizando AsType<T>.

delphi
var
  Endereco: TEnderecoData;
begin
  Endereco :=
    TApiFactory.New
      .BaseURL('https://viacep.com.br')
      .Resource('/ws/01001000/json/')
      .Get
      .AsType<TEnderecoData>;

  ShowMessage(
    'CEP: ' + Endereco.cep + sLineBreak +
    'Cidade: ' + Endereco.localidade
  );
end;

🔐 Autenticação com Token Bearer

A Factory também pode ser utilizada em APIs que utilizam autenticação baseada em token.

delphi
var
  LoginReq: TLoginRequest;
  User: TUserData;
  ObjAPI: IApiClient;
begin

  ObjAPI :=
    TApiFactory.New
      .BaseURL('https://dummyjson.com');

  LoginReq := TLoginRequest.Create;
  try
    LoginReq.username := 'emilys';
    LoginReq.password := 'emilyspass';

    ObjAPI.AuthProvider(
      TAuthProvider.Create(
        ObjAPI
          .Resource('/auth/login')
          .AddBody(LoginReq)
          .Post
          .AsType<TLoginResponse>
          .accessToken
      )
    );

  finally
    LoginReq.Free;
  end;

  User :=
    ObjAPI
      .Resource('/auth/me')
      .Get
      .AsType<TUserData>;

  ShowMessage(User.firstname);
end;

📤 POST — Envio de objeto JSON

Objetos Delphi podem ser utilizados diretamente como corpo da requisição.

delphi
var
  ProdutoReq: TProdutoData;
  ProdutoResp: TProdutoData;
begin

  ProdutoReq := TProdutoData.Create;
  try
    ProdutoReq.title := 'Meu novo produto';
    ProdutoReq.price := 99.9;

    ProdutoResp :=
      TApiFactory.New
        .BaseURL('https://dummyjson.com')
        .Resource('/products/add')
        .AddBody(ProdutoReq)
        .Post
        .AsType<TProdutoData>;

  finally
    ProdutoReq.Free;
  end;

  ShowMessage(ProdutoResp.title);
end;

✏️ PUT — Atualização de dados

Também é possível enviar JSON diretamente para endpoints que utilizam PUT.

delphi
var
  ProdutoResp: TProdutoData;
  Json: TJSONObject;
begin

  Json := TJSONObject.Create;
  try

    Json.AddPair(
      'title',
      'iPhone 15 Pro Max Atualizado'
    );

    ProdutoResp :=
      TApiFactory.New
        .BaseURL('https://dummyjson.com')
        .Resource('/products/1')
        .AddBody(Json.ToString)
        .Put
        .AsType<TProdutoData>;

  finally
    Json.Free;
  end;

  ShowMessage(ProdutoResp.title);
end;

📚 Conversão automática de Arrays

A Factory também permite converter respostas contendo arrays JSON diretamente para arrays de objetos Delphi.

delphi
var
  Users: TArray<TUserData>;
  User: TUserData;
  LMessage: string;
begin

  Users :=
    TApiFactory.New
      .BaseURL('https://jsonplaceholder.typicode.com')
      .Resource('/posts')
      .Get
      .AsArray<TUserData>;

  for User in Users do
  begin
    LMessage :=
      LMessage +
      'Id: ' + User.id.ToString + sLineBreak +
      'Title: ' + User.title + sLineBreak;
  end;

  ShowMessage(LMessage);
end;

🏢 Caso real de utilização

Um dos objetivos deste projeto foi verificar a aplicação da abstração em um cenário além dos exemplos didáticos.

A API Factory foi utilizada em uma integração real de um sistema legado Delphi com uma API REST, responsável pelo envio dos movimentos de caixas para um serviço externo.

Nesse fluxo, o sistema precisava:

  • identificar o caixa que seria processado;
  • montar dinamicamente o endpoint;
  • configurar credenciais de autenticação;
  • adicionar headers específicos da API;
  • obter os movimentos relacionados ao caixa;
  • transformar os dados em JSON;
  • realizar uma requisição POST;
  • interpretar a resposta da API;
  • tratar erros de comunicação;
  • registrar a requisição e seu resultado;
  • informar o resultado da operação ao usuário.

O exemplo abaixo representa a implementação utilizada nesse cenário.


🔴 Implementação sem a API Factory

Antes da utilização da abstração, a comunicação HTTP era realizada diretamente por meio do THTTPClient.

Nesse modelo, o código da aplicação precisava gerenciar explicitamente a infraestrutura da requisição.

delphi
lHttpClient := THTTPClient.Create;
try
  lHttpClient.CustomHeaders['Authorization'] :=
    'Basic ' + RetornarCredenciais;

  lHttpClient.CustomHeaders['pdv-version'] :=
    '8.6.0';

  lHttpClient.CustomHeaders['backEnd-version'] :=
    '8.6.0';

  lJsonBody :=
    TStringStream.Create(
      TJSON.ObjectToJsonString(
        TArray<TObject>(
          RetornarMovimentos(
            lCaixas.FieldByName(
              'CXSEQUENCIA'
            ).AsInteger
          )
        )
      ),
      TEncoding.UTF8
    );

  lResponse :=
    lHttpClient.Post(
      RetornarURL(lI) + lResource,
      lJsonBody,
      TNetHeader.Create(
        'Content-Type',
        'application/json'
      )
    );

  lRetorno :=
    TJson.JsonToObject<TRetornoData>(
      lResponse.ContentAsString
    );

finally
  lJsonBody.Free;
  lHttpClient.Free;
end;

Além da execução da requisição, a implementação precisa lidar diretamente com a criação e liberação dos objetos utilizados na comunicação.

Também é necessário realizar manualmente a configuração dos headers, criação do corpo da requisição, serialização dos dados e conversão da resposta.


🟢 Implementação utilizando a API Factory

Com a API Factory, o mesmo fluxo pode ser implementado de forma mais declarativa.

delphi
lRetorno :=
  TApiFactory.New
    .BaseURL(RetornarURL(lI))
    .Resource(lResource)
    .AddHeader('Authorization', 'Basic ' + RetornarCredenciais)
    .AddHeader('pdv-version', '8.6.0')
    .AddHeader('backEnd-version','8.6.0')
    .AddBody(TArray<TObject>(RetornarMovimentos(lCaixas.FieldByName('CXSEQUENCIA').AsInteger)))
    .Post
    .AsType<TRetornoData>;

A chamada passa a representar diretamente a intenção da operação:

text
Base URL
   ↓
Resource
   ↓
Headers
   ↓
Body
   ↓
POST
   ↓
Resposta tipada

Os detalhes relacionados à criação do cliente HTTP, envio da requisição, serialização, desserialização e gerenciamento dos recursos ficam concentrados na camada de abstração.


📊 Comparação das implementações

Responsabilidade Sem API Factory Com API Factory
Criação do cliente HTTP Código consumidor API Factory
Configuração de headers Código consumidor API Factory
Criação do corpo HTTP Código consumidor API Factory
Serialização JSON Código consumidor API Factory
Execução da requisição Código consumidor API Factory
Desserialização da resposta Código consumidor API Factory
Gerenciamento de recursos Código consumidor API Factory
Regra de negócio Misturada à infraestrutura Mais isolada da infraestrutura
Reutilização Menor Maior
Padronização Manual Centralizada

Resultado

A principal diferença observada não está apenas na quantidade de linhas de código.

A proposta da API Factory é centralizar as responsabilidades de infraestrutura, permitindo que o código que utiliza a integração tenha uma responsabilidade mais próxima da regra de negócio.

Em outras palavras:

A API Factory não elimina a complexidade da comunicação HTTP; ela encapsula essa complexidade em um único ponto da aplicação.


🔄 Comparação simplificada

Sem abstração

text
Regra de negócio
      │
      ├── Cria HTTP Client
      ├── Configura Headers
      ├── Cria JSON
      ├── Executa POST
      ├── Trata Response
      ├── Converte JSON
      └── Libera recursos

Com API Factory

text
Regra de negócio
      │
      ▼
 API Factory
      │
      ├── HTTP Client
      ├── Headers
      ├── JSON
      ├── Request
      ├── Response
      └── Recursos

📐 Arquitetura proposta

A ideia geral da solução pode ser representada da seguinte forma:

text
┌──────────────────────────────┐
│       Sistema Delphi         │
│                              │
│  Regra de negócio / Forms    │
└──────────────┬───────────────┘
               │
               │
               ▼
┌──────────────────────────────┐
│         API Factory          │
│                              │
│  • Base URL                  │
│  • Resource                  │
│  • Headers                   │
│  • Authentication            │
│  • Request Body              │
│  • HTTP Client               │
│  • JSON Serialization        │
│  • JSON Deserialization      │
│  • Error Handling            │
└──────────────┬───────────────┘
               │
               │ HTTP/HTTPS
               ▼
┌──────────────────────────────┐
│           API REST           │
└──────────────────────────────┘

📦 Como utilizar

Para utilizar a API Factory em um projeto Delphi:

1. Adicione a unit ao projeto

Adicione a unit APIFactory.pas e suas dependências ao projeto.

2. Configure a URL base

delphi
TApiFactory.New
  .BaseURL('https://minha-api.com');

3. Defina o recurso

delphi
.Resource('/clientes');

4. Configure os headers necessários

delphi
.AddHeader(
  'Authorization',
  'Bearer ' + Token
);

5. Execute a operação

delphi
.Get;

ou:

delphi
.Post;
delphi
.Put;
delphi
.Delete;

6. Converta a resposta

delphi
.AsType<TMinhaClasse>;

ou:

delphi
.AsArray<TMinhaClasse>;

🔄 Fluxo de utilização

text
Sistema Legado Delphi
        │
        ▼
    API Factory
        │
        ▼
    HTTP/HTTPS
        │
        ▼
      API REST
        │
        ▼
      JSON
        │
        ▼
    API Factory
        │
        ▼
Sistema Legado Delphi

A aplicação não precisa conhecer todos os detalhes internos utilizados para estabelecer a comunicação HTTP, mantendo a integração centralizada na camada proposta.


🧪 Validação

A solução foi avaliada considerando tanto os aspectos técnicos quanto sua utilização prática.

Foram considerados:

  • testes de requisições HTTP;
  • testes de envio e recebimento de JSON;
  • testes de conversão para objetos;
  • testes de conversão de arrays;
  • tratamento de erros;
  • tratamento de exceções;
  • reutilização da implementação;
  • comparação entre a abordagem tradicional e a abstração proposta;
  • utilização em uma integração real de sistema legado.

A aplicação prática permitiu observar a utilização da abstração em um cenário real de integração entre um sistema Delphi e uma API REST.


🎓 Contexto acadêmico

Este projeto foi desenvolvido como parte de um Trabalho de Conclusão de Curso (TCC), tendo como tema a melhoria do processo de integração entre sistemas legados desenvolvidos em Delphi e APIs REST modernas.

A proposta surgiu a partir da necessidade de reduzir a repetição de código e centralizar responsabilidades relacionadas à comunicação HTTP.

Além da implementação acadêmica, a solução foi aplicada em um cenário real, permitindo comparar a abordagem tradicional baseada diretamente no THTTPClient com a utilização da API Factory.

O código-fonte é disponibilizado com finalidade acadêmica e de estudo, permitindo que outros desenvolvedores possam analisar a implementação, reproduzir os exemplos e utilizar os conceitos apresentados em seus próprios projetos.


💡 Principais benefícios

Menos código repetitivo

A infraestrutura necessária para realizar uma requisição HTTP fica concentrada na API Factory.

Centralização

Configurações e comportamentos relacionados à comunicação podem ser mantidos em um único ponto.

Reutilização

A mesma estrutura pode ser utilizada por diferentes integrações e endpoints.

Manutenção

Alterações relacionadas à comunicação HTTP podem ser realizadas na camada de abstração, reduzindo a necessidade de alterações espalhadas pelo sistema.

Legibilidade

O código consumidor passa a representar melhor a intenção da operação:

delphi
TApiFactory.New
  .BaseURL(URL)
  .Resource('/clientes')
  .AddBody(Cliente)
  .Post
  .AsType<TClienteResponse>;

em vez de precisar lidar diretamente com toda a infraestrutura necessária para executar a requisição.


👤 Autor

Cauã Rocha Leite

Projeto desenvolvido para fins acadêmicos e de estudo sobre integração de sistemas legados Delphi com APIs REST.


📄 Licença

Uso acadêmico