Saltearse al contenido

Arquitectura del API Gateway

Arquitectura del API Gateway

Descripción General

El API Gateway sirve como el único punto de entrada para todas las solicitudes de clientes en la plataforma Algesta. Construido con NestJS 11.x y TypeScript, implementa el patrón CQRS (Command Query Responsibility Segregation) para manejar enrutamiento, autenticación, orquestación de servicios y estandarización de respuestas.

Responsabilidades Clave:

  • Enrutar solicitudes HTTP entrantes a los microservicios backend apropiados
  • Validar tokens JWT y aplicar control de acceso basado en roles (RBAC)
  • Orquestar llamadas de servicio y agregar respuestas
  • Estandarizar formatos de respuesta con traceId para seguimiento de solicitudes
  • Implementar patrones de resiliencia (circuit breaker, health checks)
  • Proporcionar documentación OpenAPI/Swagger para todos los endpoints

Stack Tecnológico:

  • Framework: NestJS 11.0.1
  • Lenguaje: TypeScript
  • Patrón de Arquitectura: CQRS
  • Comunicación: Redis/Kafka para integración de microservicios
  • Autenticación: Basada en JWT con @nestjs/jwt 11.0.0
  • Documentación: Swagger/OpenAPI vía @nestjs/swagger 11.2.0

La posición del gateway en la arquitectura general está definida en workspace.dsl como el contenedor API Gateway dentro del sistema Algesta.


Arquitectura y Estructura de Módulos

El gateway está organizado en más de 20 módulos de funcionalidades, cada uno responsable de un área de dominio específica. Todos los módulos están ubicados en src/infrastructure/modules/.

Descripción General de Módulos

MóduloControladoresPropósitoMicroservicio Conectado
AuthModuleauth.controller.ts
auth.otp.controller.ts
Autenticación de usuario, registro, restablecimiento de contraseña, validación OTPMS_AUTH
OrdersModuleorders-management.controller.ts
location.controller.ts
Creación de órdenes, gestión, seguimiento del ciclo de vidaMS_ORDERS
ProviderModuleprovider.controller.tsGestión de perfil de proveedor, asignaciones de órdenesMS_PROVIDER
AuctionModuleauction.controller.tsPublicación de subastas, presentación de ofertas, asignación de proveedoresMS_PROVIDER
ClientModuleclient.controller.tsAprobación de órdenes del cliente, solicitudes de cambios, calificaciones de proveedoresMS_ORDERS
NotificationModulenotification.controller.tsCreación y entrega de notificacionesMS_NOTIFICATIONS
MessagesModulemessages.controller.tsFuncionalidad de mensajería y chatMS_MESSAGES
DocumentoModuleDocumento.controller.tsCarga, recuperación y generación de PDF de documentosMS_ORDERS
AssetsModuleassets.controller.tsGestión de activos, generación de CVMS_ORDERS
CompanyModulecompany.controller.tsRegistro y gestión de empresasMS_AUTH
EmployeeModuleemployee.controller.tsRegistro de empleados y validación OTPMS_AUTH
ServiceModuleservice.controller.tsCatálogo de servicios y asociaciones de proveedoresMS_PROVIDER
TechnicianModuletechnician.controller.tsGestión de técnicos y asignaciones de órdenesMS_PROVIDER

Patrón de Implementación CQRS

El gateway implementa el patrón CQRS para separar operaciones de lectura y escritura:

Comandos (Operaciones de Escritura):

  • Usados para operaciones que cambian el estado (Crear, Actualizar, Eliminar)
  • Ejemplos: CreateOrderCommand, UpdateOrderCommand, PublishAuctionCommand
  • Los manejadores ejecutan lógica de negocio y se comunican con microservicios
  • Ubicados en src/application/commands/

Consultas (Operaciones de Lectura):

  • Usadas para operaciones de recuperación de datos
  • Ejemplos: GetOrderByIdQuery, GetAllOrdersQuery, ListAuctionsQuery
  • Los manejadores obtienen datos de microservicios
  • Ubicados en src/application/queries/

Flujo del Manejador:

  1. El controlador recibe la solicitud HTTP
  2. El controlador crea un objeto Command o Query
  3. CommandBus o QueryBus despacha al manejador apropiado
  4. El manejador se comunica con el microservicio vía ClientProxy
  5. El manejador procesa la respuesta y retorna el resultado
  6. El controlador formatea la respuesta y la envía al cliente

Archivos de Referencia:

  • src/app.module.ts - Módulo principal de la aplicación con todas las importaciones
  • src/infrastructure/modules/*.module.ts - Módulos de funcionalidades

Enrutamiento y Orquestación de Servicios

Configuración Global

  • Prefijo Global: /api (configurado en main.ts)
  • URL Base (Desarrollo): http://localhost:3000/api
  • Swagger UI: http://localhost:3000/api/docs

Tabla de Enrutamiento de Endpoints Clave

Método HTTPEndpointComando/ConsultaMicroservicio DestinoAutenticación RequeridaRoles
POST/api/auth/loginLoginCommandMS_AUTHNo-
POST/api/auth/register-webRegisterWebCommandMS_AUTHNo-
POST/api/ordersCreateOrderCommandMS_ORDERSOpcional-
GET/api/ordersGetAllOrdersQueryMS_ORDERSNo*-
GET/api/orders/:orderIdGetOrderByIdQueryMS_ORDERSNo*-
PATCH/api/orders/:orderIdUpdateOrderCommandMS_ORDERSADMIN, AGENT
PATCH/api/orders/publish/:orderIdPublishOrderCommandMS_ORDERSADMIN, AGENT
GET/api/provider/auctionsListAuctionsQueryMS_PROVIDERPROVIDER
POST/api/provider/auction-responseSubmitAuctionOfferCommandMS_PROVIDERPROVIDER
POST/api/auction/publishPublishAuctionCommandMS_PROVIDERADMIN, AGENT
POST/api/client/submit-approvalSubmitApprovalCommandMS_ORDERSCLIENT

*Nota: GET /api/orders y GET /api/orders/:orderId no tienen decoradores @UseGuards(JwtAuthGuard) en la implementación actual, haciéndolos públicamente accesibles. Esto puede ser intencional para permitir el seguimiento de órdenes sin autenticación.

Diagrama de Flujo de Solicitudes

sequenceDiagram
    participant Client as Cliente
    participant Gateway as API Gateway
    participant Guard as JwtAuthGuard
    participant Controller as Controlador
    participant Handler as Manejador de Comando/Consulta
    participant MS as Microservicio

    Client->>Gateway: Solicitud HTTP + Token JWT
    Gateway->>Guard: Validar Token
    Guard->>MS: Validar con MS_AUTH
    MS-->>Guard: Token Válido + Datos de Usuario
    Guard-->>Gateway: Adjuntar Usuario a Solicitud
    Gateway->>Controller: Enrutar a Controlador
    Controller->>Handler: Ejecutar Comando/Consulta
    Handler->>MS: Enviar Mensaje (Redis/Kafka)
    MS-->>Handler: Respuesta
    Handler-->>Controller: Retornar Resultado
    Controller-->>Gateway: Formatear Respuesta
    Gateway-->>Client: Respuesta HTTP + TraceId

Patrones de Orquestación de Servicios

1. Llamadas Directas a Microservicios:

  • El controlador recibe la solicitud → El manejador envía mensaje a un solo microservicio → Se retorna la respuesta

2. Agregación Multi-Servicio:

  • El manejador envía mensajes a múltiples microservicios
  • Agrega las respuestas en un solo resultado
  • Ejemplo: Detalles de orden con información del proveedor y datos del activo

3. Manejo de Errores con Circuit Breaker:

  • CircuitBreakerService envuelve las llamadas a microservicios
  • Fallo rápido cuando el servicio no está disponible
  • Mecanismos de respaldo para degradación elegante

Archivos de Referencia:

  • src/infrastructure/controllers/*.controller.ts - Enrutamiento de solicitudes
  • src/application/handlers/ - Lógica de negocio y orquestación

Autenticación y Autorización

El gateway implementa autenticación integral basada en JWT con control de acceso basado en roles. Para documentación detallada, ver Autenticación del API Gateway.

Resumen

Flujo de Autenticación:

  1. El usuario envía credenciales a /api/auth/login
  2. El gateway reenvía al microservicio MS_AUTH
  3. MS_AUTH valida y genera token JWT
  4. El token se retorna al cliente
  5. El cliente incluye el token en el encabezado Authorization: Bearer <token> para solicitudes subsecuentes

Implementación de Guards:

  • JwtAuthGuard: Valida tokens JWT vía TokenValidationService

    • Extrae el token Bearer del encabezado Authorization
    • Se comunica con MS_AUTH para validar el token
    • Adjunta datos del usuario al objeto request.user
    • Verifica expiración del token, estado del usuario, verificación de email
  • RolesGuard: Aplica control de acceso basado en roles

    • Lee roles requeridos de metadata del decorador @Roles
    • Compara con user.role del token JWT
    • Permite acceso si el usuario tiene cualquiera de los roles requeridos

Roles Soportados:

  • ADMIN: Acceso completo al sistema
  • AGENT: Gestión de órdenes, curación de proveedores
  • PROVIDER: Participación en subastas, cumplimiento de órdenes
  • CLIENT: Creación de órdenes, flujos de trabajo de aprobación
  • EMPLOYEE: Operaciones específicas de la empresa

Decoradores:

@UseGuards(JwtAuthGuard, RolesGuard)
@Roles(UserRole.ADMIN, UserRole.AGENT)
@Patch('orders/:orderId')
async updateOrder(@CurrentUser() user: AuthenticatedUser, @Param('orderId') orderId: string) {
// El usuario está autenticado y tiene rol ADMIN o AGENT
}

Archivos de Referencia:

  • src/shared/guards/jwt-auth.guard.ts
  • src/shared/guards/roles.guard.ts
  • src/shared/services/token-validation.service.ts

Integración de Microservicios

El gateway se conecta a 5 microservicios backend usando mensajería Redis o Kafka.

Configuración de Capa de Transporte

El tipo de transporte es configurable vía la variable de entorno MESSAGING_TYPE.

Configuración Redis:

{
host: process.env.REDIS_HOST,
port: parseInt(process.env.REDIS_PORT),
password: process.env.REDIS_PASSWORD,
db: parseInt(process.env.REDIS_DB),
retryAttempts: parseInt(process.env.REDIS_RETRY_ATTEMPTS) || 5,
retryDelay: parseInt(process.env.REDIS_RETRY_DELAY) || 3000,
connectTimeout: parseInt(process.env.REDIS_CONNECT_TIMEOUT) || 60000,
lazyConnect: true // Establecer conexión en el primer uso
}

Configuración Kafka:

{
clientId: process.env.KAFKA_CLIENT_ID,
brokers: process.env.KAFKA_BROKERS?.split(','),
consumer: {
groupId: process.env.KAFKA_GROUP_ID,
allowAutoTopicCreation: true,
sessionTimeout: 30000,
},
producer: {
allowAutoTopicCreation: true,
}
}

Microservicios Registrados

El ClientsModule en app.module.ts registra conexiones para:

  1. MS_AUTH - Autenticación y gestión de usuarios
  2. MS_ORDERS - Ciclo de vida y gestión de órdenes
  3. MS_MESSAGES - Mensajería y notificaciones
  4. MS_PROVIDER - Gestión de proveedores y subastas
  5. MS_NOTIFICATIONS - Entrega de notificaciones

Patrón de Comunicación

Solicitud-Respuesta vía método send():

const result = await this.msOrdersClient
.send("orders.create", createOrderDto)
.toPromise();

Circuit Breaker para Resiliencia

El gateway implementa el patrón Circuit Breaker para prevenir fallos en cascada:

  • Estados: CLOSED (normal), OPEN (fallando), HALF_OPEN (recuperándose)
  • Umbral de Fallos: 5 fallos consecutivos (configurable)
  • Timeout de Recuperación: 60 segundos (configurable)
  • Mecanismos de Respaldo: Degradación elegante cuando los servicios no están disponibles

Para información detallada, ver Patrones de Resiliencia del API Gateway.

Archivos de Referencia:

  • src/config/config.transport.ts - Configuración de transporte
  • src/infrastructure/messaging/circuit-breaker.service.ts

Medidas de Seguridad

Configuración de CORS

Configurado en main.ts:

app.enableCors({
origin: true, // Permitir todos los orígenes en desarrollo
methods: "GET,HEAD,PUT,PATCH,POST,DELETE,OPTIONS",
credentials: true,
});

Recomendación para Producción: Configurar orígenes permitidos específicos en lugar de true.

Validación

ValidationPipe Global:

app.useGlobalPipes(
new ValidationPipe({
whitelist: true, // Eliminar propiedades desconocidas
transform: true, // Transformar payloads a instancias de DTO
forbidNonWhitelisted: true, // Lanzar error en propiedades desconocidas
})
);

Validación de DTO con class-validator:

export class CreateOrderDto {
@IsString()
@IsNotEmpty()
service: string;
@IsString()
@IsOptional()
description?: string;
@IsEnum(OrderPriority)
priority: OrderPriority;
}

Filtro de Excepciones Global

HttpExceptionFilter proporciona respuestas de error estandarizadas:

  • Captura todas las excepciones lanzadas en la aplicación
  • Formatea errores con código de estado, mensaje, timestamp, path, traceId
  • Registra errores con Winston logger

Ejemplo de Respuesta de Error (BaseResponseDto):

{
"success": false,
"message": "Validación fallida",
"data": null,
"error": {
"statusCode": 400,
"error": "Bad Request",
"message": "Validación fallida",
"timestamp": "2025-01-15T10:30:00Z",
"path": "/api/orders",
"method": "POST",
"traceId": "uuid-aquí"
}
}

Nota: Todas las respuestas de error siguen la estructura BaseResponseDto<null> como se define en HttpExceptionFilter, con un success: false externo, message, data: null, y un objeto error anidado que contiene información detallada del error.

Interceptor de Respuesta

ResponseInterceptor estandariza todas las respuestas exitosas:

  • Agrega traceId para seguimiento de solicitudes
  • Incluye timestamp, código de estado, mensaje
  • Proporciona estructura consistente en todos los endpoints
  • Si un manejador retorna un objeto que contiene success o código de estado, el interceptor lo deja como está

Referencia: src/infrastructure/rest/interceptors/response.interceptor.ts

Ejemplo de Respuesta Exitosa (Envoltorio por Defecto):

{
"statusCode": 200,
"message": "Órdenes recuperadas exitosamente",
"timestamp": "2025-01-15T10:30:00Z",
"path": "/api/orders",
"method": "GET",
"data": [...],
"traceId": "uuid-aquí"
}

Nota: Algunos endpoints pueden retornar estructuras de respuesta personalizadas (como BaseResponseDto) si el manejador retorna explícitamente un objeto con campos success o código de estado. En tales casos, el ResponseInterceptor pasa la respuesta sin envolverla.

Envoltorio de Respuesta Estándar

El gateway usa dos mecanismos para estandarizar respuestas:

1. ResponseInterceptor (Respuestas Exitosas)

Envuelve todas las respuestas exitosas con metadatos:

  • statusCode: Código de estado HTTP (200, 201, etc.)
  • message: Mensaje de éxito (auto-generado basado en método y path)
  • timestamp: Timestamp ISO 8601
  • path: URL de la solicitud
  • method: Método HTTP
  • data: Payload de respuesta real
  • traceId: Identificador único de solicitud

Envoltorio Condicional: Si un manejador retorna un objeto que ya contiene campos success o statusCode, el interceptor lo pasa sin envolver. Esto permite que los endpoints retornen estructuras de respuesta personalizadas cuando sea necesario.

Referencia: src/infrastructure/rest/interceptors/response.interceptor.ts

2. HttpExceptionFilter (Respuestas de Error)

Todas las respuestas de error siguen la estructura BaseResponseDto<null>:

  • Nivel externo: success: false, message, data: null
  • Objeto error interno con:
    • statusCode: Código de estado HTTP
    • error: Tipo/nombre del error
    • message: Mensaje de error
    • timestamp: Timestamp ISO 8601
    • path: URL de la solicitud
    • method: Método HTTP
    • traceId: Identificador único de solicitud
    • details (opcional): Detalles de error de validación

Referencia: src/infrastructure/rest/filters/http-exception.filter.ts y src/shared/dtos/rest/base-response.dto.ts

Brechas de Seguridad

No Implementado Actualmente:

  • Limitación de tasa (se recomienda @nestjs/throttler)
  • Helmet para headers de seguridad
  • Límites de tamaño de solicitud
  • Lista blanca/negra de IPs

Archivos de Referencia:

  • src/main.ts
  • src/infrastructure/rest/filters/http-exception.filter.ts
  • src/infrastructure/rest/interceptors/response.interceptor.ts

Health Checks y Monitoreo

Endpoint de Salud del Gateway

GET /health (no requiere autenticación)

Retorna el estado de salud del gateway para verificaciones del balanceador de carga:

{
"status": "ok",
"service": "api-gateway",
"timestamp": "2025-01-15T10:30:00Z",
"uptime": 3600,
"version": "1.0.0",
"environment": "development"
}

Valores de Estado: "ok" cuando está saludable. En estados de error, el campo estado puede indicar una condición de error (dependiente de la implementación).

Nota: Este endpoint está registrado antes del prefijo global /api para fácil acceso por balanceadores de carga y no usa el envoltorio de respuesta estándar.

Referencia: src/main.ts y src/shared/health/health.service.ts

Verificación de Salud de Servicios Downstream

GET /api/health/services (requiere autenticación)

Verifica la salud de todos los microservicios conectados. Los servicios actualmente configurados son ms-auth, ms-patient y ms-ai-integrator como se define en ServicesHealthService.getConfiguredServices().

{
"status": "healthy",
"timestamp": "2025-01-15T10:30:00Z",
"services": [
{
"service": "ms-auth",
"status": "healthy",
"responseTime": 45
},
{
"service": "ms-patient",
"status": "healthy",
"responseTime": 32
},
{
"service": "ms-ai-integrator",
"status": "unhealthy",
"responseTime": 5100,
"error": "Timeout de conexión"
}
],
"summary": {
"total": 3,
"healthy": 2,
"unhealthy": 1,
"degraded": 0
}
}

Valores de Estado:

  • Estado de nivel superior: 'healthy', 'degraded', o 'unhealthy'
  • Estado por servicio: 'healthy', 'unhealthy', o 'timeout' (como se define en ServiceHealthStatus)

Configuración:

  • Timeout: Configurable vía HEALTH_CHECK_TIMEOUT (por defecto: 5000ms)
  • URLs de Servicios: Configurables vía variables de entorno MS_*_URL
    • MS_AUTH_URL (por defecto: http://localhost:3001)
    • MS_PATIENT_URL (por defecto: http://localhost:3003)
    • MS_AI_INTEGRATOR_URL (por defecto: http://localhost:3002)
  • Verificaciones en Paralelo: Todos los servicios se verifican concurrentemente para rendimiento
  • Estado Agregado:
    • healthy si todos los servicios están saludables
    • degraded si algunos servicios están saludables
    • unhealthy si ningún servicio está saludable

Integración con Kubernetes:

  • Sonda de liveness: GET /health
  • Sonda de readiness: GET /api/health/services

Archivos de Referencia:

  • src/main.ts (registro de endpoint de salud del gateway)
  • src/shared/health/health.service.ts
  • src/shared/health/services-health.service.ts (ver getConfiguredServices() y tipo ServiceHealthStatus)

Documentación OpenAPI/Swagger

Acceso a Swagger UI

URL: http://localhost:3000/api/docs

Documentación de API interactiva con:

  • Todos los endpoints organizados por tags
  • Esquemas de solicitud/respuesta
  • Soporte de autenticación (Bearer JWT)
  • Funcionalidad de prueba en vivo

Configuración

Configurado en main.ts:

const config = new DocumentBuilder()
.setTitle("API Gateway - Onklinic") // NOTA: Debería actualizarse a "Algesta"
.setDescription("API Gateway para la plataforma Algesta")
.setVersion("1.0")
.addBearerAuth()
.build();
const document = SwaggerModule.createDocument(app, config);
SwaggerModule.setup("api/docs", app, document);

Decoradores de API

Decoradores de Controlador y Endpoint:

@ApiTags("Orders")
@Controller("orders")
export class OrdersManagementController {
@Post()
@ApiOperation({ summary: "Crear nueva orden" })
@ApiResponse({
status: 201,
description: "Orden creada exitosamente",
type: OrderResponseDto,
})
@ApiResponse({ status: 400, description: "Error de validación" })
@ApiBearerAuth()
@UseGuards(JwtAuthGuard)
async createOrder(@Body() dto: CreateOrderDto) {
// Implementación
}
}

Documentación de DTO:

export class CreateOrderDto {
@ApiProperty({
description: "Tipo de servicio",
example: "PLUMBING",
enum: ServiceType,
})
@IsEnum(ServiceType)
service: ServiceType;
@ApiProperty({
description: "Descripción de la orden",
example: "Tubería con fuga en el baño",
required: false,
})
@IsString()
@IsOptional()
description?: string;
}

Decoradores Personalizados:

  • @ApiStandardResponses: Agrega respuestas comunes de éxito/error
  • @ApiAuthCommonResponses: Agrega respuestas de error relacionadas con autenticación

Archivos de Referencia:

  • src/main.ts - Configuración de Swagger
  • src/shared/decorators/*.decorator.ts - Decoradores personalizados
  • src/shared/dtos/ - DTOs de respuesta

Patrón Circuit Breaker

El gateway implementa el patrón Circuit Breaker para resiliencia contra fallos de servicios downstream.

Estados

stateDiagram-v2
    [*] --> CLOSED
    CLOSED --> OPEN: Umbral de fallos excedido
    OPEN --> HALF_OPEN: Timeout de recuperación
    HALF_OPEN --> CLOSED: Solicitud exitosa
    HALF_OPEN --> OPEN: Solicitud fallida
  • CLOSED: Operación normal, todas las solicitudes pasan
  • OPEN: Umbral de fallos excedido, las solicitudes fallan inmediatamente
  • HALF_OPEN: Probando recuperación, solicitudes limitadas permitidas

Configuración

Variables de entorno:

  • CIRCUIT_BREAKER_FAILURE_THRESHOLD: Número de fallos antes de abrir (por defecto: 5)
  • CIRCUIT_BREAKER_RECOVERY_TIMEOUT: Tiempo antes de intentar recuperación (por defecto: 60000ms)
  • CIRCUIT_BREAKER_MONITORING_PERIOD: Período para rastreo de fallos (por defecto: 300000ms)

Ejemplo de Uso

await this.circuitBreaker.execute(
async () => {
return await this.msOrdersClient
.send("orders.get", { orderId })
.toPromise();
},
async () => {
// Respuesta de respaldo cuando el circuito está abierto
return { status: "service_unavailable", cached: true };
}
);

Para documentación detallada, ver Patrones de Resiliencia del API Gateway.

Archivo de Referencia: src/infrastructure/messaging/circuit-breaker.service.ts


Stack Tecnológico

DependenciaVersiónPropósito
@nestjs/core11.0.1Framework core de NestJS
@nestjs/common11.0.1Utilidades comunes de NestJS
@nestjs/cqrs11.0.3Implementación del patrón CQRS
@nestjs/microservices11.1.1Comunicación de microservicios
@nestjs/swagger11.2.0Documentación OpenAPI
@nestjs/jwt11.0.0Autenticación JWT
ioredis5.6.1Cliente Redis
redis5.1.0Transporte Redis para microservicios
kafkajs2.2.4Cliente Kafka
class-validator0.14.1Validación de DTO
class-transformer0.5.1Transformación de objetos
nest-winston1.10.0Integración de logger Winston
@azure/storage-blob12.25.0Azure Blob Storage para carga de archivos
puppeteer23.11.1Generación de PDF

Archivo de Referencia: algesta-api-gateway-nestjs/package.json


Configuración de Entorno

Variables de Entorno Requeridas

VariableDescripciónPor DefectoEjemplo
Mensajería
MESSAGING_TYPECapa de transporte (REDIS o KAFKA)REDISKAFKA
Configuración de Redis
REDIS_HOSTHost del servidor Redislocalhostredis.example.com
REDIS_PORTPuerto del servidor Redis63796379
REDIS_PASSWORDContraseña de Redis-secret123
REDIS_DBNúmero de base de datos Redis00
REDIS_RETRY_ATTEMPTSIntentos de reconexión510
REDIS_RETRY_DELAYRetraso entre reintentos (ms)30005000
REDIS_CONNECT_TIMEOUTTimeout de conexión (ms)6000030000
Configuración de Kafka
KAFKA_CLIENT_IDIdentificador del cliente Kafkaalgesta-gatewayapi-gateway
KAFKA_BROKERSLista de brokers separados por comaslocalhost:9092kafka1:9092,kafka2:9092
KAFKA_GROUP_IDID del grupo de consumidoresalgesta-gateway-groupgateway-consumers
URLs de Microservicios
MS_AUTH_URLURL del microservicio de Authhttp://localhost:3001http://ms-auth:3001
MS_PATIENT_URLURL del microservicio de Patienthttp://localhost:3002http://ms-patient:3002
MS_AI_INTEGRATOR_URLURL del integrador de IAhttp://localhost:3003http://ms-ai:3003
Circuit Breaker
CIRCUIT_BREAKER_FAILURE_THRESHOLDFallos antes de abrir510
CIRCUIT_BREAKER_RECOVERY_TIMEOUTTimeout de intento de recuperación (ms)60000120000
CIRCUIT_BREAKER_MONITORING_PERIODVentana de monitoreo (ms)300000600000
Health Checks
HEALTH_CHECK_TIMEOUTTimeout de health check (ms)500010000
Aplicación
SERVICE_NAMENombre del servicio para logsapi-gatewayalgesta-gateway
SERVICE_VERSIONVersión del servicio1.0.01.2.3
NODE_ENVEntornodevelopmentproduction
PORTPuerto del servidor HTTP30008080

Diagramas de Flujo de Solicitudes

Flujo de Solicitud Autenticada

sequenceDiagram
    participant Client as Cliente
    participant Gateway
    participant JwtGuard as JwtAuthGuard
    participant RolesGuard
    participant Controller as Controlador
    participant Handler as Manejador
    participant MS as Microservicio

    Client->>Gateway: POST /api/orders<br/>Authorization: Bearer token
    Gateway->>JwtGuard: canActivate()
    JwtGuard->>MS: Validar token (MS_AUTH)
    MS-->>JwtGuard: Datos de usuario
    JwtGuard->>Gateway: Adjuntar usuario a solicitud
    Gateway->>RolesGuard: canActivate()
    RolesGuard->>RolesGuard: Verificar user.role vs @Roles
    RolesGuard->>Gateway: Autorizado
    Gateway->>Controller: createOrder()
    Controller->>Handler: CreateOrderCommand
    Handler->>MS: Enviar mensaje 'orders.create'
    MS-->>Handler: Orden creada
    Handler-->>Controller: Retornar resultado
    Controller-->>Gateway: OrderResponseDto
    Gateway-->>Client: 201 Created + traceId

Flujo de Solicitud No Autenticada

sequenceDiagram
    participant Client as Cliente
    participant Gateway
    participant Controller as Controlador
    participant Handler as Manejador
    participant MS as Microservicio

    Client->>Gateway: POST /api/auth/login<br/>{ email, password }
    Gateway->>Controller: login()
    Controller->>Handler: LoginCommand
    Handler->>MS: Enviar mensaje 'auth.login'
    MS->>MS: Validar credenciales
    MS->>MS: Generar JWT
    MS-->>Handler: { token, user }
    Handler-->>Controller: Retornar resultado
    Controller-->>Gateway: LoginResponseDto
    Gateway-->>Client: 200 OK + Token JWT

Flujo de Manejo de Errores con Circuit Breaker

sequenceDiagram
    participant Client as Cliente
    participant Gateway
    participant Handler as Manejador
    participant CB as CircuitBreaker
    participant MS as Microservicio

    Client->>Gateway: GET /api/orders
    Gateway->>Handler: GetOrdersQuery
    Handler->>CB: execute()

    alt Circuito CERRADO
        CB->>MS: Enviar solicitud
        MS-->>CB: Timeout/Error
        CB->>CB: Incrementar contador de fallos
        CB-->>Handler: Lanzar error
    else Circuito ABIERTO
        CB-->>Handler: Fallo rápido (sin llamada a MS)
    else Circuito SEMI-ABIERTO
        CB->>MS: Solicitud de prueba
        alt Éxito
            MS-->>CB: Éxito
            CB->>CB: Transición a CERRADO
            CB-->>Handler: Retornar resultado
        else Fallo
            MS-->>CB: Error
            CB->>CB: Transición a ABIERTO
            CB-->>Handler: Lanzar error
        end
    end

    Handler-->>Gateway: Error
    Gateway->>Gateway: HttpExceptionFilter
    Gateway-->>Client: Respuesta de error + traceId

Referencias Cruzadas

Documentación Relacionada

Diagramas de Arquitectura

  • Modelo C4: Ver workspace.dsl para diagramas de arquitectura completos
  • Contexto del Sistema: Muestra el API Gateway como punto de entrada para todos los tipos de cliente
  • Diagrama de Contenedores: Muestra las conexiones del gateway con microservicios y bases de datos

Brechas y Recomendaciones

Brechas Actuales

  1. Limitación de Tasa: No implementado

    • Impacto: Vulnerable a ataques DoS y abuso
    • Recomendación: Implementar @nestjs/throttler con límites por usuario y por IP
  2. Headers de Seguridad: Helmet no configurado

    • Impacto: Faltan headers de seguridad (CSP, HSTS, etc.)
    • Recomendación: Agregar middleware helmet
  3. Versionado de API: No implementado

    • Impacto: Cambios disruptivos difíciles de manejar
    • Recomendación: Implementar versionado basado en URL (/api/v1/orders)
  4. Título de Swagger: Referencia “Onklinic” en lugar de “Algesta”

    • Impacto: Inconsistencia de marca
    • Recomendación: Actualizar título en main.ts
  5. README del Repositorio: Faltante

    • Impacto: Nuevos desarrolladores sin documentación de onboarding
    • Recomendación: Crear README completo con instrucciones de configuración
  6. Caché de Solicitudes: No implementado

    • Impacto: Consultas repetidas a microservicios para los mismos datos
    • Recomendación: Implementar caché Redis para endpoints de lectura intensiva
  7. Recolección de Métricas: No implementado

    • Impacto: Observabilidad limitada de rendimiento y uso
    • Recomendación: Agregar métricas Prometheus y dashboards Grafana
  8. Política de Timeout Global: No configurada

    • Impacto: Las solicitudes pueden colgarse indefinidamente
    • Recomendación: Implementar interceptor de timeout con valores por defecto configurables
  9. Tokens de Refresco: No implementado

    • Impacto: Los usuarios deben re-autenticarse cuando el JWT expira
    • Recomendación: Implementar mecanismo de refresh token
  10. MFA: Parcialmente implementado pero no aplicado

    • Impacto: Seguridad reducida para operaciones sensibles
    • Recomendación: Completar implementación de MFA y aplicar para cuentas de administrador

Recomendaciones de Pruebas

Ejemplo: Probar Autenticación

Ventana de terminal
# Login para obtener token JWT
curl -X POST http://localhost:3000/api/auth/login \
-H "Content-Type: application/json" \
-d '{"email":"user@example.com","password":"password123"}'
# Respuesta:
# {
# "statusCode": 200,
# "data": {
# "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
# "user": {
# "id": "user-123",
# "email": "user@example.com",
# "role": "CLIENT"
# }
# },
# "traceId": "uuid-aquí"
# }
# Usar token para acceder a endpoint protegido
curl http://localhost:3000/api/orders \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."

Ejemplo: Probar Salud del Gateway

Ventana de terminal
# Verificar salud del gateway
curl http://localhost:3000/health
# Verificar salud de todos los servicios (requiere autenticación)
curl http://localhost:3000/api/health/services \
-H "Authorization: Bearer <token>"

Ejemplo: Probar Control de Acceso Basado en Roles

Ventana de terminal
# Rol CLIENT intentando operación solo de ADMIN (debería fallar con 403)
curl -X PATCH http://localhost:3000/api/orders/order-123 \
-H "Authorization: Bearer <client-token>" \
-H "Content-Type: application/json" \
-d '{"status":"PUBLISHED"}'
# Respuesta esperada:
# {
# "statusCode": 403,
# "message": "Recurso prohibido",
# "error": "Forbidden",
# "traceId": "uuid-aquí"
# }

Resumen

El API Gateway sirve como el punto de entrada robusto y escalable para la plataforma Algesta, implementando patrones estándar de la industria para autenticación, autorización, resiliencia y orquestación de servicios. Construido sobre NestJS con arquitectura CQRS, proporciona una clara separación de responsabilidades y excelente experiencia de desarrollo.

Fortalezas Clave:

  • Arquitectura modular con clara separación de dominios
  • Autenticación JWT completa con RBAC
  • Patrón circuit breaker para resiliencia
  • Respuestas estandarizadas con seguimiento de solicitudes
  • Documentación Swagger extensa

Mejoras Prioritarias:

  1. Agregar limitación de tasa y headers de seguridad
  2. Implementar versionado de API
  3. Agregar métricas Prometheus y monitoreo
  4. Completar implementación de MFA
  5. Implementar caché de solicitudes para rendimiento
  6. Agregar README completo al repositorio

Para detalles de implementación, ver la documentación con referencias cruzadas arriba.