workspace-v1/shared/libs/rate-limiting/README.md
rckrdmrd 66161b1566 feat: Workspace-v1 complete migration with NEXUS v3.4
Sistema NEXUS v3.4 migrado con:

Estructura principal:
- core/orchestration: Sistema SIMCO + CAPVED (27 directivas, 28 perfiles)
- core/catalog: Catalogo de funcionalidades reutilizables
- shared/knowledge-base: Base de conocimiento compartida
- devtools/scripts: Herramientas de desarrollo
- control-plane/registries: Control de servicios y CI/CD
- orchestration/: Configuracion de orquestacion de agentes

Proyectos incluidos (11):
- gamilit (submodule -> GitHub)
- trading-platform (OrbiquanTIA)
- erp-suite con 5 verticales:
  - erp-core, construccion, vidrio-templado
  - mecanicas-diesel, retail, clinicas
- betting-analytics
- inmobiliaria-analytics
- platform_marketing_content
- pos-micro, erp-basico

Configuracion:
- .gitignore completo para Node.js/Python/Docker
- gamilit como submodule (git@github.com:rckrdmrd/gamilit-workspace.git)
- Sistema de puertos estandarizado (3005-3199)

Generated with NEXUS v3.4 Migration System
EPIC-010: Configuracion Git y Repositorios
2026-01-04 03:37:42 -06:00

6.5 KiB

Limitación de Tasa (Rate Limiting)

Versión: 1.0.0 Origen: projects/gamilit Estado: Producción Última actualización: 2025-12-08


Descripción

Sistema de limitación de tasa para proteger APIs contra abuso:

  • Rate limiting por IP/usuario
  • Configuración por endpoint
  • Headers HTTP estándar
  • Respuestas 429 con Retry-After

Características

Característica Descripción
Por IP Limita requests por dirección IP
Por Usuario Limita requests por usuario autenticado
Por Endpoint Configuración individual por ruta
Global Límite base para toda la aplicación
Headers Estándar X-RateLimit-Limit, X-RateLimit-Remaining, Retry-After

Stack Tecnológico

backend:
  framework: NestJS
  library: "@nestjs/throttler"
  storage: "Memory (default) | Redis (producción)"

Dependencias NPM

{
  "@nestjs/throttler": "^5.x"
}

Para producción con Redis:

{
  "@nestjs/throttler-storage-redis": "^0.x",
  "redis": "^4.x"
}

Configuración Básica

En módulo principal

import { ThrottlerModule, ThrottlerGuard } from '@nestjs/throttler';
import { APP_GUARD } from '@nestjs/core';

@Module({
  imports: [
    ThrottlerModule.forRoot([{
      ttl: 60000,  // 60 segundos
      limit: 100,  // 100 requests por TTL
    }]),
  ],
  providers: [
    {
      provide: APP_GUARD,
      useClass: ThrottlerGuard,
    },
  ],
})
export class AppModule {}

Configuración por ambiente

ThrottlerModule.forRootAsync({
  imports: [ConfigModule],
  inject: [ConfigService],
  useFactory: (config: ConfigService) => ([{
    ttl: config.get('THROTTLE_TTL', 60000),
    limit: config.get('THROTTLE_LIMIT', 100),
  }]),
})

Uso por Endpoint

Sobrescribir límites

import { Throttle, SkipThrottle } from '@nestjs/throttler';

@Controller('auth')
export class AuthController {

  // Más estricto: 5 intentos por minuto
  @Throttle({ default: { limit: 5, ttl: 60000 } })
  @Post('login')
  login() {}

  // Omitir rate limiting
  @SkipThrottle()
  @Get('public')
  publicEndpoint() {}
}

En controlador completo

@Controller('api')
@Throttle({ default: { limit: 50, ttl: 60000 } })
export class ApiController {
  // Todos los endpoints heredan el límite
}

Múltiples Límites

ThrottlerModule.forRoot([
  {
    name: 'short',
    ttl: 1000,    // 1 segundo
    limit: 3,     // 3 requests por segundo
  },
  {
    name: 'medium',
    ttl: 10000,   // 10 segundos
    limit: 20,    // 20 requests por 10 segundos
  },
  {
    name: 'long',
    ttl: 60000,   // 1 minuto
    limit: 100,   // 100 requests por minuto
  },
])

Usar en endpoint:

@Throttle({
  short: { limit: 1, ttl: 1000 },
  long: { limit: 10, ttl: 60000 },
})
@Post('expensive-operation')
expensiveOperation() {}

Rate Limiting por Usuario

Custom ThrottlerGuard

import { Injectable, ExecutionContext } from '@nestjs/common';
import { ThrottlerGuard } from '@nestjs/throttler';

@Injectable()
export class CustomThrottlerGuard extends ThrottlerGuard {
  protected async getTracker(req: Record<string, any>): Promise<string> {
    // Si hay usuario autenticado, usar su ID
    if (req.user?.id) {
      return req.user.id;
    }
    // Fallback a IP
    return req.ip;
  }
}

Registrar:

providers: [
  {
    provide: APP_GUARD,
    useClass: CustomThrottlerGuard,
  },
],

Almacenamiento Redis (Producción)

import { ThrottlerStorageRedisService } from '@nestjs/throttler-storage-redis';
import Redis from 'ioredis';

ThrottlerModule.forRootAsync({
  imports: [ConfigModule],
  inject: [ConfigService],
  useFactory: (config: ConfigService) => ({
    throttlers: [{
      ttl: config.get('THROTTLE_TTL', 60000),
      limit: config.get('THROTTLE_LIMIT', 100),
    }],
    storage: new ThrottlerStorageRedisService(new Redis({
      host: config.get('REDIS_HOST', 'localhost'),
      port: config.get('REDIS_PORT', 6379),
    })),
  }),
})

Headers de Respuesta

El módulo agrega automáticamente:

X-RateLimit-Limit: 100         # Límite máximo
X-RateLimit-Remaining: 95      # Requests restantes
X-RateLimit-Reset: 1234567890  # Timestamp de reset

En respuesta 429:

Retry-After: 60                # Segundos hasta poder reintentar

Excepciones Personalizadas

import { ThrottlerException } from '@nestjs/throttler';

// En el guard personalizado
protected throwThrottlingException(): void {
  throw new ThrottlerException(
    'Demasiadas solicitudes. Por favor, espere un momento.',
  );
}

Variables de Entorno

# Configuración básica
THROTTLE_TTL=60000        # Ventana de tiempo en ms
THROTTLE_LIMIT=100        # Requests por ventana

# Redis (producción)
REDIS_HOST=localhost
REDIS_PORT=6379

Casos de Uso Comunes

1. Login (anti brute-force)

@Throttle({ default: { limit: 5, ttl: 300000 } }) // 5 por 5 minutos
@Post('login')
login() {}

2. Registro (anti spam)

@Throttle({ default: { limit: 3, ttl: 3600000 } }) // 3 por hora
@Post('register')
register() {}

3. API pública

@Throttle({ default: { limit: 1000, ttl: 3600000 } }) // 1000 por hora
@Get('public-data')
getData() {}

4. Endpoints costosos

@Throttle({ default: { limit: 10, ttl: 60000 } }) // 10 por minuto
@Post('generate-report')
generateReport() {}

Métricas y Logging

@Injectable()
export class ThrottlerLoggerGuard extends ThrottlerGuard {
  protected async handleRequest(
    context: ExecutionContext,
    limit: number,
    ttl: number,
  ): Promise<boolean> {
    const req = context.switchToHttp().getRequest();
    const tracker = await this.getTracker(req);

    const result = await super.handleRequest(context, limit, ttl);

    if (!result) {
      this.logger.warn(`Rate limit exceeded for: ${tracker}`);
    }

    return result;
  }
}

Adaptaciones Necesarias

  1. Límites: Ajustar según tráfico esperado
  2. Storage: Memory para desarrollo, Redis para producción
  3. Tracker: IP vs Usuario según necesidad
  4. Mensajes: Personalizar respuestas 429

Referencias


Mantenido por: Sistema NEXUS Proyecto origen: Gamilit Platform