Ir al contenido

El Rest Client Moderno que Delphi Merecía: Conozca Dext Rest Client

Header Concept

Delphi siempre ha sido sinónimo de productividad. Sin embargo, a medida que nuestras aplicaciones evolucionan hacia arquitecturas distribuidas y microservicios, la forma en que consumimos APIs necesita acompañar esta modernidad.

A menudo, el enfoque tradicional basado en componentes visuales (TRestClient), aunque excelente para prototipado, puede agregar complejidad innecesaria y verbosidad al código de producción, especialmente cuando lidiamos con peticiones dinámicas, autenticación compleja y concurrencia.

En el desarrollo del Dext Framework, buscamos una experiencia de desarrollo que uniera el rendimiento nativo de Delphi con la elegancia de las APIs fluidas modernas.

El resultado es Dext.Net.RestClient. Y cambiará la forma en que consumes APIs en Delphi.

Dext Rest Client adopta un enfoque Code-First. Olvide los componentes visuales. El código debe contar la historia completa de la petición.

Cómo lo hacíamos (Modo Tradicional):

  • Arrastrar componente TRestClient1
  • Arrastrar TRestRequest1 (y vincularlo al cliente)
  • Arrastrar TRestResponse1 (y vincularlo a la petición)
  • En código: RestRequest1.Params.AddItem('Authorization', 'Bearer ' + Token, pkHTTPHEADER);
  • RestRequest1.Execute;

Cómo lo hacemos con Dext (Modo Fluido):

uses
Dext.Net.RestClient; // La única unit que necesitas
var
Users: TList<TUser>;
begin
Users := RestClient('https://api.ejemplo.com')
.BearerToken(MyJwtToken)
.Timeout(5000)
.Get<TList<TUser>>('/users?role=admin') // ¡Serialización automática de Listas!
.Await; // Síncrono o Asíncrono, tú eliges
end;

Es limpio, legible y, lo más importante, seguro en tiempo de compilación. Si cambias el tipo de retorno, el compilador te avisa.

2. Rendimiento: El Poder del Connection Pooling

Sección titulada «2. Rendimiento: El Poder del Connection Pooling»

Aquí está el secreto que hace a Dext mucho más rápido que la implementación estándar para escenarios de alta carga.

Crear una instancia de TNetHttpClient es costoso (Handles de OS, SSL Handshake, etc). Si creas y destruyes un Cliente para cada petición en un bucle, tu rendimiento sufre.

El TRestClient de Dext es, en realidad, un Record ligero que actúa como fachada para un Connection Pool Thread-Safe.

  • Cuando haces una petición, tomamos un THttpClient “caliente” (ya creado) del pool.
  • Ejecutamos la petición.
  • Lo devolvemos al pool inmediatamente.

Esto permite escalar tu aplicación para manejar alta concurrencia de forma eficiente, reutilizando recursos de conexiones TCP/SSL costosos. Y sí, es 100% Thread-Safe por diseño.

3. Arquitectura Asíncrona y “Delphi Threads”

Sección titulada «3. Arquitectura Asíncrona y “Delphi Threads”»

Dext no depende de llamadas manuales como ProcessMessages (que pueden generar efectos secundarios de reentrancia) para mantener la UI receptiva. Está construido sobre la biblioteca Dext.Threading, utilizando un pool de threads inteligente (Work Stealing).

En mi libro, “Delphi Multithreading”, dedico un tema entero a explicar por qué cancelar una tarea es tan vital como ejecutarla.

Imagina un “Auto-Complete”. El usuario escribe “D”, “e”, “l”… no quieres 3 peticiones compitiendo. Quieres cancelar la anterior tan pronto como llega la siguiente.

Con Dext, esto es trivial:

procedure TFormSearch.EditChange(Sender: TObject);
begin
// Cancela la búsqueda anterior automáticamente
CancellationTokenSource.Cancel;
CancellationTokenSource := TCancellationTokenSource.Create;
RestClient.Get<TSearchResult>('/search')
.QueryParam('q', EditSearch.Text)
.Cancellation(CancellationTokenSource.Token) // Integración nativa
.OnComplete(procedure(Res: TSearchResult)
begin
// Actualiza Grid en el Thread Principal automáticamente
Grid.DataSource := Res.Verify;
end)
.Start;
end;

¿Y si necesitas autenticarte antes de buscar datos? En lugar de anidar callbacks (“Callback Hell”), puedes encadenar operaciones de forma lineal usando el método .ThenBy.

Dext.Net.RestClient se integra perfectamente con Dext.Threading.Async, permitiendo que el resultado de una petición alimente a la siguiente:

RestClient.Get<TToken>('/auth/token')
.ThenBy<TUser>(
function(Token: TToken): TUser
begin
// Este bloque corre automáticamente tras el éxito de la primera petición.
// Y dentro de él, ¡podemos hacer otra llamada síncrona (Await) sin congelar la UI!
Result := RestClient.Get('/profile')
.Header('Authorization', Token.AccessToken)
.Execute<TUser>
.Await;
end)
.OnComplete(procedure(User: TUser)
begin
// Solo llega aquí cuando TODO termina con éxito
UserProfile.Text := User.Name;
end)
.Start;

Esto transforma flujos complejos en código plano y fácil de leer.

4. Innovación: Archivos .http (El Estándar del Mercado)

Sección titulada «4. Innovación: Archivos .http (El Estándar del Mercado)»

Esta es la killer feature para la productividad.

Dext trae soporte nativo a archivos .http (estándar usado por VS Code e IntelliJ). Puedes documentar y probar tus APIs en archivos de texto simple dentro de tu proyecto:

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

Sintaxis simple y poderosa: Variables con @, separador de peticiones con ###.

Y en tu código Delphi, ejecutas esto directamente:

uses
Dext.Http.Parser;
var
Requests: THttpRequestCollection;
Req: THttpRequestInfo;
begin
// 1. Carga el archivo
Requests := THttpRequestParser.ParseFile('orders.http');
try
// 2. Busca la petición por nombre
Req := Requests.FindByName('Crear Nuevo Pedido');
// 3. Resuelve variables (interpolando {{baseUrl}})
THttpRequestParser.ResolveRequest(Req, Requests.Variables);
// 4. Ejecuta
RestClient.Execute(Req).Await;
finally
Requests.Free;
end;
end;

Integramos este soporte en Dext Dashboard. Mira esto:

Dext HTTP Dashboard

Basta de mantener Colecciones desactualizadas en herramientas externas. Con Dext Dashboard, ejecutas los propios archivos .http de tu proyecto. Es la misma “fuente de la verdad” para el código, para las pruebas y para el desarrollador.

  • Edición con Syntax Highlighting: Escribe tus .http con comodidad.
  • Ejecución Real: El Dashboard corre la petición usando el mismo motor Dext.Net.RestClient de tu aplicación. Lo que ves es exactamente lo que tu código recibirá.
  • Historial y Logs: Analiza tiempo de respuesta, headers y payload JSON formateado.

Esto te mantiene en el “Flow State”. Código, Prueba, Documentación… todo en el mismo lugar.

6. Testabilidad: La Pesadilla de los DataModules Terminó

Sección titulada «6. Testabilidad: La Pesadilla de los DataModules Terminó»

Cualquier desarrollador que haya intentado crear pruebas unitarias para un formulario o DataModule acoplado a componentes TRestClient sabe el dolor que es. Necesitas instanciar el formulario, asegurar que el IDE no cree conexiones automáticas, y es casi imposible “fingir” (mock) una respuesta del servidor sin levantar un servidor HTTP local.

Dext.Net.RestClient fue diseñado pensando en TDD (Test Driven Development).

La arquitectura basada en interfaces (IRestClient) te permite inyectar mocks fácilmente usando Dext.Mocks y validar resultados con Dext.Testing, sin depender de bibliotecas externas.

Ejemplo de Prueba de Regla de Negocio (Aislado de la Red):

uses
Dext.Mocks, Dext.Assertions;
procedure TFreightServiceTest.DebeManejarErrorDeAPI;
var
MockClient: Mock<IHttpClient>; // Interfaz abstraída
Service: TFreightService;
begin
// Configura el Mock
MockClient := Mock<IHttpClient>.Create;
// Define comportamiento: Cuando llame 'Calculate', retorna error 503
MockClient.Setup.Returns(503).When.Calculate(Arg.Any<string>);
// Inyecta el mock (¡nada de red real!)
Service := TFreightService.Create(MockClient.Instance);
// Valida comportamiento con Fluent Assertions
// Si la API falla, el servicio debe retornar 0.0 (regla de negocio)
Should(Service.CalculateFreight('12345-678')).Be(0.0);
end;

Esta capacidad de desacoplar tu lógica de negocio de la infraestructura de red es lo que diferencia aplicaciones profesionales de códigos legados difíciles de mantener.

7. El Ciclo Completo: Pruebas de Integración con Controladores

Sección titulada «7. El Ciclo Completo: Pruebas de Integración con Controladores»

Elevemos el nivel. Imagina probar tu servidor HTTP Dext (Controller) usando el propio Dext Rest Client y archivos .http como masa de pruebas.

Considera este Controlador 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 escribir una Prueba de Integración que levanta el servidor en memoria, inyecta un Service Mockeado en el Controller, y usa los archivos .http para validar la respuesta.

Primero, el archivo de escenario scenarios/create-order.http:

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

Ahora, la prueba que ejecuta este escenario contra el servidor en memoria:

procedure TIntegrationTest.TestCreateOrderFlow;
var
Server: TDextApplication;
MockService: Mock<IOrderService>;
Response: IRestResponse;
RequestInfo: THttpRequestInfo;
Requests: THttpRequestCollection;
begin
// 1. Configura el Mock del Service (Backend)
MockService := Mock<IOrderService>.Create;
MockService.Setup.Returns(True).When.ProcessOrder(Arg.Any<TOrder>);
// 2. Levanta el Servidor en Memoria inyectando el Mock
// DextApplication puede ser instanciada ligera para pruebas
Server := TDextApplication.Create;
Server.Services.AddSingleton<IOrderService>(MockService.Instance);
Server.Start(8090); // Puerto aleatorio/dedicado para prueba
try
// 3. Carga el archivo .http
// Dext tiene un parser nativo para este formato
Requests := THttpRequestParser.ParseFile('scenarios/create-order.http');
try
// Obtiene la petición por el nombre definido (### Crear Nuevo Pedido)
RequestInfo := Requests.FindByName('Crear Nuevo Pedido');
// Resuelve variables (URL del servidor de prueba)
RequestInfo.Url := 'http://localhost:8090' + RequestInfo.Url;
// 4. Ejecuta la petición real
Response := RestClient
.Execute(RequestInfo) // ¡Método que acepta el objeto del parser!
.Await;
// 5. Valida la respuesta
Should(Response.StatusCode).Be(201);
Should(Response.ContentString).Contain('"status":"created"');
finally
Requests.Free;
end;
finally
Server.Stop;
Server.Free;
end;
end;

Esto es End-to-End Testing elegante. Tu archivo .http sirve como documentación viva y como driver para tus pruebas automatizadas.

Tal vez estés pensando: “Esto es hermoso, pero mi sistema es un ERP Desktop monolítico de 10 años, no puedo reescribir todo para Web ahora”.

La buena noticia: No necesitas hacerlo.

Dext.Net.RestClient está totalmente desacoplado. Puedes comenzar a usarlo hoy en tu proyecto VCL o FMX y comenzar a reemplazar esas llamadas HTTP verbosas poco a poco.

No necesitas migrar la base de datos, no necesitas crear Controladores. Solo agrega la unit al uses y comienza a escribir código nuevo (o refactorizar el antiguo) con calidad moderna. Es la puerta de entrada perfecta para modernizar tu stack sin el riesgo de una reescrita total.

Si has llegado hasta aquí, has visto inyección de dependencias, expressions, generics, programación asíncrona real y pruebas fluidas.

Si hubiera ocultado las palabras clave begin/end, probablemente jurarías que estabas leyendo un artículo sobre C# o TypeScript, ¿no? Pues sí. Delphi ha evolucionado. Y con Dext Framework, garantizamos que tu código evolucione junto.

Dext.Net.RestClient no es solo un wrapper HTTP; es una modernización de la forma en que pensamos en conectividad en Delphi. Une la seguridad de tipos de Pascal, la elegancia de las APIs fluidas y el poder del asincronismo moderno.

Este proyecto es Open Source y hecho por la comunidad, para la comunidad.

Si te gustó lo que viste y quieres apoyar esta evolución del ecosistema Delphi, visita nuestro repositorio y deja una Estrella ⭐. Esto nos ayuda mucho a continuar construyendo herramientas de alto nivel para ti.

👉 Dale una ⭐ en GitHub ahora: github.com/cesarliws/dext


Para entender profundamente cómo funciona Dext.Threading (el motor detrás de este Rest Client), revisa mi nuevo libro:

Delphi Multithreading

Consigue tu copia aquí