Pular para o conteúdo

O Rest Client Moderno que o Delphi Merecia: Conheça o Dext Rest Client

Header Concept

O Delphi sempre foi sinônimo de produtividade. No entanto, à medida que nossas aplicações evoluem para arquiteturas distribuídas e microsserviços, a forma como consumimos APIs precisa acompanhar essa modernidade.

Muitas vezes, a abordagem tradicional baseada em componentes visuais (TRestClient), embora excelente para prototipagem, pode adicionar complexidade desnecessária e verbosidade ao código de produção, especialmente quando lidamos com requisições dinâmicas, autenticação complexa e concorrência.

No desenvolvimento do Dext Framework, buscamos uma experiência de desenvolvimento que unisse a performance nativa do Delphi com a elegância das APIs fluentes modernas.

O resultado é o Dext.Net.RestClient. E ele vai mudar a forma como você consome APIs no Delphi.

O Dext Rest Client adota uma abordagem Code-First. Esqueça os componentes visuais. O código deve contar a história completa da requisição.

Como fazíamos (Modo Tradicional):

  • Arrasta componente TRestClient1
  • Arrasta TRestRequest1 (e liga no client)
  • Arrasta TRestResponse1 (e liga no request)
  • No código: RestRequest1.Params.AddItem('Authorization', 'Bearer ' + Token, pkHTTPHEADER);
  • RestRequest1.Execute;

Como fazemos com Dext (Modo Fluente):

uses
Dext.Net.RestClient; // A única unit que você precisa
var
Users: TList<TUser>;
begin
Users := RestClient('https://api.exemplo.com')
.BearerToken(MyJwtToken)
.Timeout(5000)
.Get<TList<TUser>>('/users?role=admin') // Serialização automática de Listas!
.Await; // Síncrono ou Assíncrono, você escolhe
end;

É limpo, legível e, o mais importante, seguro em tempo de compilação. Se você mudar o tipo de retorno, o compilador te avisa.

Aqui está o segredo que torna o Dext muito mais rápido que a implementação padrão para cenários de alta carga.

Criar uma instância de TNetHttpClient é caro (Handles de OS, SSL Handshake, etc). Se você cria e destrói um Client para cada requisição em um loop, sua performance sofre.

O TRestClient do Dext é, na verdade, um Record leve que atua como fachada para um Connection Pool Thread-Safe.

  • Quando você faz uma requisição, pegamos um THttpClient “quente” (já criado) do pool.
  • Executamos a requisição.
  • Devolvemos ao pool imediatamente.

Isso permite escalar sua aplicação para lidar com alta concorrência de forma eficiente, reutilizando recursos de conexões TCP/SSL custosos. E sim, é 100% Thread-Safe por design.

O Dext não depende de chamadas manuais como ProcessMessages (que podem gerar efeitos colaterais de reentrância) para manter a UI responsiva. Ele é construído sobre a biblioteca Dext.Threading, utilizando um pool de threads inteligente (Work Stealing).

Em meu livro, “Delphi Multithreading”, dedico tópico inteiro a explicar por que cancelar uma tarefa é tão vital quanto executá-la.

Imagine um “Auto-Complete”. O usuário digita “D”, “e”, “l”… você não quer 3 requisições concorrendo. Você quer cancelar a anterior assim que a próxima chega.

Com Dext, isso é trivial:

procedure TFormSearch.EditChange(Sender: TObject);
begin
// Cancela a busca anterior automaticamente
CancellationTokenSource.Cancel;
CancellationTokenSource := TCancellationTokenSource.Create;
RestClient.Get<TSearchResult>('/search')
.QueryParam('q', EditSearch.Text)
.Cancellation(CancellationTokenSource.Token) // Integração nativa
.OnComplete(procedure(Res: TSearchResult)
begin
// Atualiza Grid na Thread Principal automaticamente
Grid.DataSource := Res.Verify;
end)
.Start;
end;

E se você precisar autenticar antes de buscar dados? Em vez de aninhar callbacks (“Callback Hell”), você pode encadear operações de forma linear usando o método .ThenBy.

O Dext.Net.RestClient se integra perfeitamente ao Dext.Threading.Async, permitindo que o resultado de uma requisição alimente a próxima:

RestClient.Get<TToken>('/auth/token')
.ThenBy<TUser>(
function(Token: TToken): TUser
begin
// Este bloco roda automaticamente após o sucesso da primeira requisição.
// E dentro dele, podemos fazer outra chamada síncrona (Await) sem travar a UI!
Result := RestClient.Get('/profile')
.Header('Authorization', Token.AccessToken)
.Execute<TUser>
.Await;
end)
.OnComplete(procedure(User: TUser)
begin
// Só chega aqui quando TUDO terminar com sucesso
UserProfile.Text := User.Name;
end)
.Start;

Isso transforma fluxos complexos em código plano e fácil de ler.

4. Inovação: Arquivos .http (O Padrão de Mercado)

Seção intitulada “4. Inovação: Arquivos .http (O Padrão de Mercado)”

Esta é a killer feature para produtividade.

O Dext traz suporte nativo a arquivos .http (padrão usado pelo VS Code e IntelliJ). Você pode documentar e testar suas APIs em arquivos texto simples dentro do seu projeto:

@baseUrl = https://api.production.com
@authToken = eyJhbGciOiJIUzI1Ni...
### Criar Novo Pedido
POST {{baseUrl}}/orders
Authorization: Bearer {{authToken}}
Content-Type: application/json
{
"productId": 1050,
"qty": 5
}

Sintaxe simples e poderosa: Variáveis com @, separador de requisições com ###.

E no seu código Delphi, você executa isso diretamente:

uses
Dext.Http.Parser;
var
Requests: THttpRequestCollection;
Req: THttpRequestInfo;
begin
// 1. Carrega o arquivo
Requests := THttpRequestParser.ParseFile('orders.http');
try
// 2. Busca a requisição pelo nome
Req := Requests.FindByName('Criar Novo Pedido');
// 3. Resolve variáveis (interpolando {{baseUrl}})
THttpRequestParser.ResolveRequest(Req, Requests.Variables);
// 4. Executa
RestClient.Execute(Req).Await;
finally
Requests.Free;
end;
end;

Nós integramos esse suporte no Dext Dashboard. Veja isso:

Dext HTTP Dashboard

Chega de manter Collections desatualizadas em ferramentas externas. Com o Dext Dashboard, você executa os próprios arquivos .http do seu projeto. É a mesma “fonte da verdade” para o código, para os testes e para o desenvolvedor.

  • Edição com Syntax Highlighting: Escreva seus .http com conforto.
  • Execução Real: O Dashboard roda a requisição usando o mesmo motor Dext.Net.RestClient da sua aplicação. O que você vê é exatamente o que seu código vai receber.
  • Histórico e Logs: Analise tempo de resposta, headers e payload JSON formatado.

Isso mantém você no “Flow State”. Código, Teste, Documentação… tudo no mesmo lugar.

6. Testabilidade: O Pesadelo dos DataModules Acabou

Seção intitulada “6. Testabilidade: O Pesadelo dos DataModules Acabou”

Qualquer desenvolvedor que já tentou criar testes unitários para um formulário ou DataModule acoplado a componentes TRestClient sabe a dor que é. Você precisa instanciar o formulário, garantir que a IDE não crie conexões automáticas, e é quase impossível “fingir” (mock) uma resposta do servidor sem subir um servidor HTTP local.

O Dext.Net.RestClient foi desenhado pensando em TDD (Test Driven Development).

A arquitetura baseada em interfaces (IRestClient) permite que você injete mocks facilmente usando o Dext.Mocks e valide resultados com o Dext.Testing, sem depender de bibliotecas externas.

Exemplo de Teste de Regra de Negócio (Isolado da Rede):

uses
Dext.Mocks, Dext.Assertions;
procedure TFreightServiceTest.DeveTratarErroDeAPI;
var
MockClient: Mock<IHttpClient>; // Interface abstraída
Service: TFreightService;
begin
// Configura o Mock
MockClient := Mock<IHttpClient>.Create;
// Define comportamento: Quando chamar 'Calculate', retorna erro 503
MockClient.Setup.Returns(503).When.Calculate(Arg.Any<string>);
// Injeta o mock (nada de rede real!)
Service := TFreightService.Create(MockClient.Instance);
// Valida comportamento com Fluent Assertions
// Se a API falha, o serviço deve retornar 0.0 (regra de negócio)
Should(Service.CalculateFreight('12345-678')).Be(0.0);
end;

Essa capacidade de desacoplar sua lógica de negócio da infraestrutura de rede é o que diferencia aplicações profissionais de códigos legados difíceis de manter.

7. O Ciclo Completo: Testes de Integração com Controllers

Seção intitulada “7. O Ciclo Completo: Testes de Integração com Controllers”

Vamos elevar o nível. Imagine testar seu servidor HTTP Dext (Controller) usando o próprio Dext Rest Client e arquivos .http como massa de testes.

Considere este Controller de Pedidos:

type
[DextController('/api/orders')]
TOrdersController = class(TController)
private
FService: IOrderService;
public
constructor Create(AService: IOrderService);
[DextPost]
function CreateOrder([Body] Order: TOrderDTO): IActionResult;
end;

Podemos escrever um Teste de Integração que sobe o servidor em memória, injeta um Service Mockado no Controller, e usa os arquivos .http para validar a resposta.

Primeiro, o arquivo de cenário scenarios/create-order.http:

### Criar Novo Pedido
POST /api/orders
Content-Type: application/json
{
"productId": 1050,
"qty": 5
}

Agora, o teste que executa esse cenário contra o servidor em memória:

procedure TIntegrationTest.TestCreateOrderFlow;
var
Server: TDextApplication;
MockService: Mock<IOrderService>;
Response: IRestResponse;
RequestInfo: THttpRequestInfo;
Requests: THttpRequestCollection;
begin
// 1. Configura o Mock do Service (Backend)
MockService := Mock<IOrderService>.Create;
MockService.Setup.Returns(True).When.ProcessOrder(Arg.Any<TOrder>);
// 2. Sobe o Servidor em Memória injetando o Mock
// DextApplication pode ser instanciada leve para testes
Server := TDextApplication.Create;
Server.Services.AddSingleton<IOrderService>(MockService.Instance);
Server.Start(8090); // Porta aleatória/dedicada para teste
try
// 3. Carrega o arquivo .http
// Dext tem um parser nativo para este formato
Requests := THttpRequestParser.ParseFile('scenarios/create-order.http');
try
// Obtém a requisição pelo nome definido (### Criar Novo Pedido)
RequestInfo := Requests.FindByName('Criar Novo Pedido');
// Resolve variáveis (URL do servidor de teste)
RequestInfo.Url := 'http://localhost:8090' + RequestInfo.Url;
// 4. Executa a requisição real
Response := RestClient
.Execute(RequestInfo) // Método que aceita o objeto do parser!
.Await;
// 5. Valida a resposta
Should(Response.StatusCode).Be(201);
Should(Response.ContentString).Contain('"status":"created"');
finally
Requests.Free;
end;
finally
Server.Stop;
Server.Free;
end;
end;

Isso é End-to-End Testing elegante. Seu arquivo .http serve como documentação viva e como driver para seus testes automatizados.

Talvez você esteja pensando: “Isso é lindo, mas meu sistema é um ERP Desktop monolítico de 10 anos, não posso reescrever tudo para Web agora”.

A boa notícia: Você não precisa.

O Dext.Net.RestClient é totalmente desacoplado. Você pode começar a usá-lo hoje no seu projeto VCL ou FMX e começar a substituir aquelas chamadas HTTP verbosas aos poucos.

Não precisa migrar o banco de dados, não precisa criar Controllers. Apenas adicione a unit ao uses e comece a escrever código novo (ou refatorizar o antigo) com qualidade moderna. É a porta de entrada perfeita para modernizar seu stack sem o risco de uma reescrita total.

Se você chegou até aqui, viu injeção de dependência, expressions, generics, programação assíncrona real e testes fluentes.

Se eu tivesse escondido as palavras-chave begin/end, você provavelmente juraria que estava lendo um artigo sobre C# ou TypeScript, não é? Pois é. O Delphi evoluiu. E com o Dext Framework, nós garantimos que o seu código evolua junto.

O Dext.Net.RestClient não é apenas um wrapper HTTP; é uma modernização da forma como pensamos em conectividade no Delphi. Ele une a segurança de tipos do Pascal, a elegância de APIs fluentes e o poder do assincronismo moderno.

Este projeto é Open Source e feito pela comunidade, para a comunidade.

Se você gostou do que viu e quer apoiar essa evolução do ecossistema Delphi, visite nosso repositório e deixe uma Estrela ⭐. Isso nos ajuda muito a continuar construindo ferramentas de alto nível para você.

👉 Dê uma ⭐ no GitHub agora: github.com/cesarliws/dext


Para entender profundamente como o Dext.Threading (o motor por trás deste Rest Client) funciona, confira meu novo livro:

Delphi Multithreading

Garanta sua cópia aqui