APIs con Dart Frog
Crea APIs RESTful profesionales con el framework minimalista de Dart
Descargar Ejemplos Completos¿Qué es Dart Frog?
Dart Frog es un framework minimalista para construir backends en Dart. Es rápido, eficiente y sigue las mejores prácticas para crear APIs RESTful modernas. Perfecto para microservicios y aplicaciones que necesitan un backend ligero pero potente.
Rápido y Ligero
Minimalista y optimizado para máximo rendimiento
API First
Diseñado específicamente para crear APIs RESTful
Sistema de Rutas
Estructura basada en archivos para definir rutas
Estructura de Archivos
Cómo funciona el sistema de rutas:
Carpetas = Rutas
Cada carpeta dentro de routes/ se convierte en una ruta de la API.
Archivos = Endpoints
Los archivos index.dart manejan las solicitudes a esa ruta.
[parámetro].dart
Archivos con corchetes capturan parámetros dinámicos en la URL.
_middleware.dart
Middleware que se ejecuta antes de las rutas en esa carpeta.
Ejemplos de rutas generadas:
Middleware: Autenticación y Validación
Los middleware en Dart Frog permiten interceptar y modificar solicitudes antes de que lleguen a los handlers. Son ideales para:
Autenticación
Validar API keys, tokens JWT, etc.
Validación
Verificar datos de entrada
Logging
Registrar solicitudes y respuestas
Transformación
Modificar solicitudes/respuestas
Middleware de Autenticación:
import 'dart:json';
import 'package:dart_frog/dart_frog.dart';
Handler middleware(Handler next) {
return (context) async {
final apikey = context.request.headers['apikey'];
if (apikey == null || apikey != '123456') {
return Response(body: jsonEncode({'error': 'Apikey no válida'}));
}
return await next(context);
};
}
Flujo del Middleware:
Solicitud HTTP llega
Cliente envía solicitud con/sin API key
Middleware intercepta
Verifica headers y API key
Validación
Si es válida → pasa al handler
Si no es válida → respuesta de error
Handler Principal: Manejo de Métodos HTTP
El archivo index.dart en cada ruta contiene la función onRequest que maneja todas las solicitudes HTTP a esa ruta.
GET
Obtener recursos
LecturaPOST
Crear recursos
CreaciónPUT
Actualizar recursos
ActualizaciónDELETE
Eliminar recursos
EliminaciónHandler para la ruta raíz:
import 'dart:json';
import 'package:dart_frog/dart_frog.dart';
Future<Response> onRequest(RequestContext context) async {
switch (context.request.method) {
case HttpMethod.get:
return Response(body: jsonEncode({
'método': 'GET',
'ruta': '/',
'mensaje': 'Bienvenido a la API'
}));
case HttpMethod.post:
final body = await context.request.json();
return Response(body: jsonEncode({
'método': 'POST',
'datos_recibidos': body,
'estado': 'creado'
}));
case HttpMethod.put:
return Response(body: jsonEncode({
'método': 'PUT',
'mensaje': 'Recurso actualizado'
}));
case HttpMethod.delete:
return Response(body: jsonEncode({
'método': 'DELETE',
'mensaje': 'Recurso eliminado'
}));
default:
return Response(
statusCode: 405,
body: 'Método no permitido'
);
}
}
Probador de API Interactivo
Respuesta de la API
{
"status": "esperando solicitud..."
}
Content-Type: application/json
Server: Dart Frog
// El código Dart se generará aquí
// basado en tu solicitud
# El comando cURL se generará aquí
Ejemplo Completo: API de Productos
CRUD Completo para Productos:
Código del Handler:
import 'dart:json';
import 'package:dart_frog/dart_frog.dart';
Future<Response> onRequest(RequestContext context) async {
// Obtener parámetros de ruta
final id = context.params['id'];
switch (context.request.method) {
case HttpMethod.get:
if (id != null) {
// GET /products/123
return Response(body: jsonEncode({
'id': id,
'nombre': 'Producto ' + id,
'precio': 99.99
}));
} else {
// GET /products
return Response(body: jsonEncode([
{'id': 1, 'nombre': 'Camisa', 'precio': 29.99},
{'id': 2, 'nombre': 'Pantalón', 'precio': 49.99}
]));
}
case HttpMethod.post:
final body = await context.request.json();
return Response(
statusCode: 201,
body: jsonEncode({
'id': 3,
'producto': body,
'estado': 'creado'
})
);
case HttpMethod.put:
final body = await context.request.json();
return Response(body: jsonEncode({
'id': id,
'producto': body,
'estado': 'actualizado'
}));
case HttpMethod.delete:
return Response(body: jsonEncode({
'id': id,
'estado': 'eliminado'
}));
default:
return Response(statusCode: 405);
}
}
Parámetros y Consultas
Parámetros de Ruta
Capturan valores directamente de la URL
/products/[id].dart
→
context.params['id']
Parámetros de Consulta
Valores opcionales después del ? en la URL
/products?categoria=shirts&orden=precio
→
context.request.uri.queryParameters
Cuerpo de la Solicitud
Datos enviados en POST/PUT
{ "nombre": "Producto", "precio": 100 }
→
await context.request.json()
Manejando todos los tipos de parámetros:
import 'dart:json';
import 'package:dart_frog/dart_frog.dart';
Future onRequest(RequestContext context) async {
// Parámetro de ruta
final productId = context.params['id'];
// Parámetros de consulta
final queryParams = context.request.uri.queryParameters;
final categoria = queryParams['categoria'];
final orden = queryParams['orden'] ?? 'nombre';
// Cuerpo de la solicitud (para POST/PUT)
Map? body;
if (context.request.method == HttpMethod.post ||
context.request.method == HttpMethod.put) {
body = await context.request.json();
}
// Headers
final authHeader = context.request.headers['authorization'];
return Response(body: jsonEncode({
'id': productId,
'categoria': categoria,
'orden': orden,
'body': body,
'autenticado': authHeader != null
}));
}
Buenas Prácticas
Validación de Entrada
Siempre valida y sanitiza los datos recibidos antes de procesarlos.
Manejo de Errores
Usa códigos HTTP apropiados y mensajes de error claros.
Documentación
Documenta tu API con OpenAPI/Swagger para facilitar su uso.
Separación de Responsabilidades
Separa lógica de negocio, acceso a datos y handlers.
Ejercicios para Practicar
Ejercicio 1: API de Blog
Crea una API para un blog con posts, comentarios y autores.
Requisitos:
- GET /posts - Listar todos los posts
- GET /posts/{id} - Obtener un post específico
- POST /posts - Crear un nuevo post (con middleware de autenticación)
- GET /posts/{id}/comments - Comentarios de un post
Ejercicio 2: Carrito de Compras
Implementa un carrito de compras con productos y usuarios.
Requisitos:
- Middleware para identificar usuarios por token
- GET /cart - Ver carrito del usuario
- POST /cart/items - Añadir producto al carrito
- DELETE /cart/items/{id} - Remover producto
- POST /cart/checkout - Finalizar compra
Ejercicio 3: API con Búsqueda Avanzada
Crea una API con filtros, ordenación y paginación.
Requisitos:
- GET /products?categoria=ropa&minPrecio=10&maxPrecio=100
- Parámetros: page, limit, sort, order
- Respuesta con metadata: total, page, totalPages
- Cache con headers ETag y Last-Modified