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

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.
1. El Fin del “Component-Hell”
Sección titulada «1. El Fin del “Component-Hell”»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ú eligesend;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).
El Gancho del Cancellation Token
Sección titulada «El Gancho del Cancellation Token»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;Pipelines y Encadenamiento (Chaining)
Sección titulada «Pipelines y Encadenamiento (Chaining)»¿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 PedidoPOST {{baseUrl}}/ordersAuthorization: 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;5. Dext Dashboard: Su “Postman” Nativo
Sección titulada «5. Dext Dashboard: Su “Postman” Nativo»Integramos este soporte en Dext Dashboard. Mira esto:
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
.httpcon comodidad. - Ejecución Real: El Dashboard corre la petición usando el mismo motor
Dext.Net.RestClientde 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 PedidoPOST /api/ordersContent-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.
8. Comience Hoy en Su Legado (VCL/FMX)
Sección titulada «8. Comience Hoy en Su Legado (VCL/FMX)»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.
Epílogo: “¿Es esto realmente Delphi?”
Sección titulada «Epílogo: “¿Es esto realmente Delphi?”»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.
Conclusión y Llamada a la Acción
Sección titulada «Conclusión y Llamada a la Acción»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
¿Quieres dominar la Asincronía en Delphi?
Sección titulada «¿Quieres dominar la Asincronía en Delphi?»Para entender profundamente cómo funciona Dext.Threading (el motor detrás de este Rest Client), revisa mi nuevo libro: