Middleware, Testing, Documentación y Seguridad Avanzada
13. Regla sobre Middleware
Regla Principal
Regla: El Middleware (
@Injectableque implementaNestMiddleware) debe usarse principalmente para lógica transversal que necesita ejecutarse antes de que la petición llegue al sistema de routing de NestJS (Guards, Pipes, Interceptors).
- Los casos de uso típicos y permitidos para Middleware incluyen: logging crudo de peticiones, manipulación de headers (ej. CORS, Helmet), integración con librerías de terceros que operan a nivel de request/response de Express/Fastify, o autenticación muy básica (aunque Passport/Guards suelen ser preferibles).
- El Middleware debe implementarse como una clase
@Injectableque implementaNestMiddlewarey su métodouse(req, res, next).- La configuración y aplicación del Middleware debe hacerse en el método
configuredel módulo correspondiente (implementandoNestModule). Se debe especificar las rutas a las que aplica (forRoutes).- Está prohibido usar Middleware para lógica de autorización (usar Guards), validación/transformación de datos de parámetros/body (usar Pipes), o manipulación de la respuesta saliente (usar Interceptors).
- Middleware reutilizable debe ubicarse en
src/common/middlewareo ensrc/middlewaresi es específico de la aplicación.
Contexto y Justificación
El Middleware opera a un nivel más bajo que los Guards, Pipes e Interceptors de NestJS, interactuando directamente con los objetos
requestyresponsedel framework subyacente (Express/Fastify). Su uso debe ser limitado a tareas que no encajan bien en los otros componentes del ciclo de vida de la petición de NestJS. Abusar del Middleware para tareas que pueden resolverse con Guards, Pipes o Interceptors viola la separación de responsabilidades y desaprovecha las características de NestJS.
Ejemplos y Contraejemplos
- Correcto (Logger Middleware Simple):
// --- src/common/middleware/logger.middleware.ts ---
import { Injectable, NestMiddleware, Logger } from '@nestjs/common';
import { Request, Response, NextFunction } from 'express';
@Injectable()
export class LoggerMiddleware implements NestMiddleware {
private readonly logger = new Logger('HTTP'); // Contexto para el Logger
use(request: Request, response: Response, next: NextFunction): void {
const { method, originalUrl, ip } = request;
const userAgent = request.get('user-agent') || '';
// Loggea antes de que la respuesta se envíe
response.on('finish', () => {
const { statusCode } = response;
const contentLength = response.get('content-length');
this.logger.log(
`${method} ${originalUrl} ${statusCode} ${contentLength} - ${userAgent} ${ip}`
);
});
next(); // Llama a next() para pasar al siguiente middleware o handler
}
}
// --- src/app.module.ts ---
import { Module, NestModule, MiddlewareConsumer } from '@nestjs/common';
import { LoggerMiddleware } from './common/middleware/logger.middleware';
// ... otros imports
@Module({ /* ... imports, controllers, providers ... */ })
export class AppModule implements NestModule {
configure(consumer: MiddlewareConsumer) {
consumer
.apply(LoggerMiddleware) // Aplica el middleware
.forRoutes('*'); // Aplica a todas las rutas
// O .forRoutes({ path: 'items', method: RequestMethod.GET }); para rutas específicas
}
} - Incorrecto: Usar Middleware para verificar un token JWT (usar
JwtAuthGuard). Usar Middleware para parsear un parámetroida número (usarParseIntPipe). Usar Middleware para envolver la respuesta en un objeto{ data: ... }(usarTransformInterceptor).
Cuándo Aplicar
Para configuración de CORS, Helmet, logging básico de request/response, o integración con librerías específicas de Express/Fastify.
Cuándo Evitar o Flexibilizar
Evitar siempre que la funcionalidad pueda implementarse usando Guards, Pipes o Interceptors, ya que estos están mejor integrados con el ecosistema NestJS (DI, metadatos, ExecutionContext).
14. Regla sobre Testing (Unit, Integration, E2E)
Regla Principal
Regla: El código generado debe ser testeable y, cuando sea aplicable o solicitado, la IA debe generar pruebas unitarias, de integración y/o E2E utilizando el framework
@nestjs/testingy Jest.
- Pruebas Unitarias (
.spec.ts):
- Deben enfocarse en una única clase (servicio, controlador, pipe, guard) aislándola de sus dependencias.
- Las dependencias (otros servicios, repositorios,
ConfigService) deben ser mockeadas usandojest.fn(),jest.spyOn()o creando mocks manuales/automáticos.- Se debe usar
Test.createTestingModulepara instanciar la clase bajo prueba, proveyendo los mocks para sus dependencias.- Los servicios deben ser testeados exhaustivamente, cubriendo la lógica de negocio y el manejo de errores.
- Los controladores deben testearse verificando que llaman a los métodos correctos del servicio con los argumentos correctos, sin reimplementar la lógica del servicio.
- Pruebas de Integración (
.integration.spec.tso similar):
- Deben verificar la interacción entre varias clases dentro de un módulo o entre módulos, usando menos mocks que las pruebas unitarias.
- Pueden requerir configurar un
TestingModulemás completo, posiblemente conectando a una base de datos de prueba (ej. en Docker).- Son útiles para probar el flujo completo de una funcionalidad a nivel de módulo.
- Pruebas E2E (
.e2e-spec.ts):
- Deben probar la aplicación completa a través de sus endpoints HTTP, como lo haría un cliente.
- Se debe usar el setup proporcionado por NestJS CLI que utiliza
supertest.- Deben instanciar la aplicación completa (
Test.createTestingModule().compile()) y realizar peticiones HTTP reales a la app en ejecución (en modo test).- Deben cubrir los flujos de usuario más críticos.
- Ubicación: Las pruebas unitarias (
.spec.ts) deben ubicarse junto al archivo que prueban. Las pruebas E2E (.e2e-spec.ts) deben estar en el directoriotest/.
Contexto y Justificación
El testing es crucial para asegurar la calidad, prevenir regresiones y facilitar refactorizaciones seguras. NestJS proporciona herramientas excelentes (
@nestjs/testing) que facilitan la creación de diferentes tipos de pruebas. Las pruebas unitarias verifican componentes aislados, las de integración aseguran la colaboración entre componentes y las E2E validan el sistema completo desde la perspectiva del cliente.
Ejemplos y Contraejemplos
- Correcto (Prueba Unitaria de Servicio):
// --- src/modules/items/services/items.service.ts ---
import { Injectable, Inject, NotFoundException } from '@nestjs/common';
import { IItemRepository, ITEM_REPOSITORY_TOKEN } from '../interfaces/item.repository.interface';
import { Item } from '../entities/item.entity';
import { CreateItemDto } from '../dtos/create-item.dto';
@Injectable()
export class ItemsService {
constructor(
@Inject(ITEM_REPOSITORY_TOKEN) private readonly itemRepository: IItemRepository,
) {}
async findById(id: string): Promise<Item> {
const item = await this.itemRepository.findById(id);
if (!item) {
throw new NotFoundException(`Item con ID ${id} no encontrado`);
}
return item;
}
async create(dto: CreateItemDto): Promise<Item> {
// ... validación de negocio ...
return this.itemRepository.create(dto);
}
}
// --- src/modules/items/services/items.service.spec.ts ---
import { Test, TestingModule } from '@nestjs/testing';
import { ItemsService } from './items.service';
import { IItemRepository, ITEM_REPOSITORY_TOKEN } from '../interfaces/item.repository.interface';
import { NotFoundException } from '@nestjs/common';
import { Item } from '../entities/item.entity';
import { CreateItemDto } from '../dtos/create-item.dto';
// Mock del repositorio
const mockItemRepository: Partial<IItemRepository> = {
findById: jest.fn(),
create: jest.fn(),
};
describe('ItemsService', () => {
let service: ItemsService;
beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
providers: [
ItemsService,
{
provide: ITEM_REPOSITORY_TOKEN,
useValue: mockItemRepository, // Usa el mock
},
],
}).compile();
service = module.get<ItemsService>(ItemsService);
jest.clearAllMocks(); // Limpia mocks entre tests
});
it('should be defined', () => {
expect(service).toBeDefined();
});
describe('findById', () => {
it('debe retornar un item si existe', async () => {
const mockId = 'some-uuid';
const expectedItem: Item = { id: mockId, name: 'Test Item', price: 100 };
(mockItemRepository.findById as jest.Mock).mockResolvedValue(expectedItem);
const result = await service.findById(mockId);
expect(result).toEqual(expectedItem);
expect(mockItemRepository.findById).toHaveBeenCalledWith(mockId);
expect(mockItemRepository.findById).toHaveBeenCalledTimes(1);
});
it('debe lanzar NotFoundException si el item no existe', async () => {
const mockId = 'non-existent-uuid';
(mockItemRepository.findById as jest.Mock).mockResolvedValue(null);
await expect(service.findById(mockId)).rejects.toThrow(NotFoundException);
expect(mockItemRepository.findById).toHaveBeenCalledWith(mockId);
});
});
describe('create', () => {
it('debe llamar al repositorio con el DTO y retornar el item creado', async () => {
const dto: CreateItemDto = { name: 'New Item', price: 200 };
const createdItem: Item = { id: 'new-uuid', ...dto };
(mockItemRepository.create as jest.Mock).mockResolvedValue(createdItem);
const result = await service.create(dto);
expect(result).toEqual(createdItem);
expect(mockItemRepository.create).toHaveBeenCalledWith(dto);
});
});
}); - Incorrecto: Pruebas unitarias que dependen de una base de datos real. Pruebas E2E mockeando servicios internos. No testear casos de error o edge cases. Pruebas de controlador que reimplementan lógica ya probada en el servicio.
Cuándo Aplicar
Siempre. Escribir código testeable y generar pruebas (especialmente unitarias para servicios) es fundamental para la calidad del software.
Cuándo Evitar o Flexibilizar
La cantidad y tipo de pruebas pueden variar según la criticidad del módulo y los recursos disponibles. Sin embargo, la lógica de negocio core siempre debería tener pruebas unitarias. Las pruebas E2E son más costosas de mantener y pueden enfocarse en los flujos críticos.
15. Regla sobre Logging
Regla Principal
Regla: Se debe implementar un sistema de logging estructurado y configurable en toda la aplicación NestJS.
- Usar
Loggerde@nestjs/common: Utilizar la claseLoggerincorporada o extenderla para necesidades básicas. Para aplicaciones más complejas o que requieran alto rendimiento/formato JSON, se recomienda usar librerías comopinoa través denestjs-pino.- Inyección de Dependencias: Inyectar
Logger(oLoggerService) en clases (servicios, controladores, etc.) en lugar de instanciarlo directamente. Se puede declarar como miembro estático en casos donde la inyección no es fácil.- Contexto: Proveer un contexto (
this.logger = new Logger('UsersService')) al crear instancias del logger para identificar fácilmente el origen del log.- Niveles de Log: Utilizar los niveles de log apropiados (
log,error,warn,debug,verbose) según la severidad y naturaleza del mensaje.- Configuración: Configurar los niveles de log habilitados (ej.
debugen desarrollo,log/warn/erroren producción) preferentemente a través de variables de entorno (LOG_LEVEL) yConfigService.- Información Útil: Incluir información relevante en los logs, como IDs de correlación, identificadores de usuario (si aplica y es seguro), y detalles del error (sin exponer información sensible).
- Prohibido
console.log: Está prohibido usarconsole.log,console.error, etc., directamente en el código de la aplicación (excepto quizás enmain.tsdurante el bootstrap inicial). Usar siempre elLoggerinyectado.
Contexto y Justificación
Un buen sistema de logging es esencial para la observabilidad, depuración y monitoreo de la aplicación en cualquier entorno. Usar el sistema de logging de NestJS (o librerías integradas) asegura consistencia, permite configurar niveles y formatos, y facilita la integración con herramientas de recolección y análisis de logs. Evitar
console.logpermite un control centralizado sobre qué se loggea y dónde.
Ejemplos y Contraejemplos
- Correcto (Uso de Logger incorporado):
import { Injectable, Logger, Scope, Inject } from '@nestjs/common';
import { REQUEST } from '@nestjs/core'; // Para obtener request-scoped data
import { Request } from 'express';
@Injectable()
export class MyService {
// Inyecta el logger estándar
private readonly logger = new Logger(MyService.name);
doSomething(userId: string, data: any) {
this.logger.log(`Iniciando operación para usuario ${userId}...`);
try {
// ... lógica de negocio ...
if (data.value < 0) {
this.logger.warn(`Valor negativo detectado: ${data.value}`, { userId, data });
}
this.logger.debug('Operación intermedia completada', { userId }); // Log de depuración
// ... más lógica ...
this.logger.log(`Operación completada exitosamente para usuario ${userId}.`);
} catch (error) {
this.logger.error(`Falló la operación para usuario ${userId}: ${error.message}`, error.stack, { userId, data });
throw error; // Relanza el error
}
}
}
// --- Logger Request-Scoped (Opcional, para incluir info de request) ---
@Injectable({ scope: Scope.REQUEST })
export class RequestScopedLogger {
private readonly logger = new Logger(RequestScopedLogger.name);
private correlationId: string;
constructor(@Inject(REQUEST) private readonly request: Request) {
// Asume que un middleware/interceptor añadió 'correlationId' al request
this.correlationId = (request as any).correlationId || 'N/A';
}
log(message: string, context?: string) {
this.logger.log(`[CorrID: ${this.correlationId}] ${message}`, context);
}
error(message: string, trace?: string, context?: string) {
this.logger.error(`[CorrID: ${this.correlationId}] ${message}`, trace, context);
}
// ... otros niveles ...
}
// --- Configuración básica en main.ts ---
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { Logger } from '@nestjs/common';
async function bootstrap() {
const app = await NestFactory.create(AppModule, {
// Habilita niveles de log basados en una variable de entorno (ej)
// logger: process.env.NODE_ENV === 'production' ? ['log', 'warn', 'error'] : ['log', 'error', 'warn', 'debug', 'verbose'],
// O usar un logger personalizado:
// logger: new MyCustomLogger()
});
// ...
await app.listen(3000);
Logger.log(`Aplicación corriendo en ${await app.getUrl()}`, 'Bootstrap');
}
bootstrap(); - Incorrecto: Usar
console.log('Usuario creado:' + userId)por toda la aplicación. No incluir contexto en los logs. Loggear información sensible (contraseñas, tokens completos). No tener niveles de log configurables.
Cuándo Aplicar
Siempre. El logging debe estar presente desde el inicio del desarrollo.
Cuándo Evitar o Flexibilizar
Nunca se debe omitir el logging. La complejidad de la configuración (logger simple vs.
nestjs-pino) puede variar según el proyecto, pero el principio de usar un logger estructurado y configurable es constante.
16. Regla sobre Documentación (Swagger/OpenAPI)
Regla Principal
Regla: Toda API REST desarrollada con NestJS debe ser documentada utilizando el estándar OpenAPI (anteriormente Swagger) a través del módulo
@nestjs/swagger.
- Setup Global: Configurar
SwaggerModuleenmain.tspara generar el documento OpenAPI y exponer la UI de Swagger (ej. en/api-docs).- Decoradores de Controlador: Usar
@ApiTagsen cada controlador para agrupar endpoints por recurso.- Decoradores de Método: Usar
@ApiOperation({ summary: '...', description: '...' })para describir cada endpoint. Usar@ApiResponse({ status: 200, description: '...', type: MyDto })para cada posible respuesta (éxito y error), especificando el DTO de respuesta si aplica.- Decoradores de DTO: Usar
@ApiProperty({ description: '...', example: '...', required: true/false })en cada propiedad de los DTOs (de entrada y salida) para documentar los schemas.- Autenticación: Documentar los esquemas de seguridad (ej. JWT, OAuth2) usando
DocumentBuilder.addBearerAuth()y@ApiBearerAuth()en los endpoints protegidos.- La documentación generada debe ser clara, completa y consistente con la implementación de la API.
Contexto y Justificación
La documentación de API es esencial para que los consumidores (frontend, otras APIs, desarrolladores) entiendan cómo interactuar con ella.
@nestjs/swaggerse integra perfectamente con los decoradores y DTOs de NestJS para generar automáticamente documentación OpenAPI interactiva y precisa, reduciendo el esfuerzo manual y asegurando que la documentación se mantenga sincronizada con el código.
Ejemplos y Contraejemplos
- Correcto (Setup y Decoradores):
// --- src/main.ts ---
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { SwaggerModule, DocumentBuilder } from '@nestjs/swagger';
import { ValidationPipe } from '@nestjs/common';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
app.useGlobalPipes(new ValidationPipe({ whitelist: true, forbidNonWhitelisted: true }));
const config = new DocumentBuilder()
.setTitle('Mi API de Items')
.setDescription('Documentación de la API para gestionar ítems')
.setVersion('1.0')
.addTag('items', 'Operaciones sobre ítems') // Añade tag global
.addTag('auth', 'Autenticación')
.addBearerAuth() // Configura seguridad Bearer (JWT)
.build();
const document = SwaggerModule.createDocument(app, config);
SwaggerModule.setup('api-docs', app, document); // Expone en /api-docs
await app.listen(3000);
}
bootstrap();
// --- src/modules/items/dtos/item.dto.ts ---
import { ApiProperty } from '@nestjs/swagger';
import { Exclude } from 'class-transformer';
export class ItemDto {
@ApiProperty({ description: 'ID único del ítem (UUID)', example: 'a1b2c3d4-...' })
id: string;
@ApiProperty({ description: 'Nombre del ítem', example: 'Laptop XYZ' })
name: string;
@ApiProperty({ description: 'Precio del ítem', example: 1299.99, type: 'number' })
price: number;
@ApiProperty({ description: 'Fecha de creación', example: '2023-10-27T10:00:00.000Z' })
createdAt: Date;
@Exclude() // No se muestra en la API (gracias a ClassSerializerInterceptor)
internalCode: string;
}
// --- src/modules/items/dtos/create-item.dto.ts ---
import { ApiProperty } from '@nestjs/swagger';
import { IsString, IsNotEmpty, IsNumber, Min } from 'class-validator';
export class CreateItemDto {
@ApiProperty({ description: 'Nombre del nuevo ítem', example: 'Teclado Mecánico', maxLength: 100 })
@IsString()
@IsNotEmpty()
name: string;
@ApiProperty({ description: 'Precio del nuevo ítem', example: 89.50, minimum: 0 })
@IsNumber()
@Min(0)
price: number;
}
// --- src/modules/items/controllers/items.controller.ts ---
import {
Controller, Get, Post, Body, Param, HttpCode, UseGuards, ParseUUIDPipe
} from '@nestjs/common';
import { ItemsService } from '../services/items.service';
import { CreateItemDto } from '../dtos/create-item.dto';
import { ItemDto } from '../dtos/item.dto';
import {
ApiTags, ApiOperation, ApiResponse, ApiParam, ApiBody, ApiBearerAuth
} from '@nestjs/swagger';
import { JwtAuthGuard } from '@app/common/guards/jwt-auth.guard'; // Asume guard JWT
@ApiTags('items') // Agrupa bajo la tag 'items'
@ApiBearerAuth() // Indica que estos endpoints requieren autenticación Bearer
@UseGuards(JwtAuthGuard)
@Controller('items')
export class ItemsController {
constructor(private readonly itemsService: ItemsService) {}
@Post()
@HttpCode(201)
@ApiOperation({ summary: 'Crea un nuevo ítem', description: 'Registra un nuevo ítem en el sistema.' })
@ApiBody({ type: CreateItemDto })
@ApiResponse({ status: 201, description: 'Ítem creado exitosamente.', type: ItemDto })
@ApiResponse({ status: 400, description: 'Datos de entrada inválidos.' })
@ApiResponse({ status: 401, description: 'No autorizado.' })
create(@Body() createItemDto: CreateItemDto): Promise<ItemDto> {
return this.itemsService.create(createItemDto);
}
@Get(':id')
@ApiOperation({ summary: 'Obtiene un ítem por su ID' })
@ApiParam({ name: 'id', description: 'UUID del ítem a buscar', type: 'string', format: 'uuid' })
@ApiResponse({ status: 200, description: 'Ítem encontrado.', type: ItemDto })
@ApiResponse({ status: 404, description: 'Ítem no encontrado.' })
@ApiResponse({ status: 401, description: 'No autorizado.' })
findOne(@Param('id', ParseUUIDPipe) id: string): Promise<ItemDto> {
return this.itemsService.findById(id);
}
} - Incorrecto: No configurar
SwaggerModule. No usar decoradores@Api...en controladores, métodos o DTOs. Documentación incompleta o inconsistente con el código. No documentar respuestas de error comunes (400, 401, 403, 404, 500).
Cuándo Aplicar
Siempre, para todas las APIs REST públicas o internas.
Cuándo Evitar o Flexibilizar
Nunca se debe omitir la documentación OpenAPI para una API NestJS. El nivel de detalle en las descripciones puede variar, pero la estructura (tags, operations, responses, schemas) debe estar completa.
17. Regla sobre Seguridad Avanzada
Regla Principal
Regla: Además de la validación de entradas (Norma 6) y autorización (Norma 9), la aplicación NestJS debe implementar medidas de seguridad adicionales para protegerse contra vulnerabilidades comunes.
- Protección de Headers (Helmet): Utilizar
helmet(middleware de Express) para establecer cabeceras HTTP seguras (X-Frame-Options, Strict-Transport-Security, etc.). Aplicarlo globalmente enmain.ts.- Protección CSRF (Cross-Site Request Forgery): Si la aplicación usa autenticación basada en cookies/sesiones (menos común en APIs REST puras que usan tokens), implementar protección CSRF usando
csurf(middleware) o mecanismos equivalentes.- Rate Limiting: Implementar limitación de peticiones (
Rate Limiting) para prevenir ataques de fuerza bruta o denegación de servicio. Usarexpress-rate-limit(middleware) o el módulo@nestjs/throttler. Aplicarlo globalmente o en endpoints sensibles.- Seguridad de Dependencias: Mantener las dependencias del proyecto actualizadas regularmente. Utilizar
npm auditoyarn audit(o herramientas como Snyk) para identificar y corregir vulnerabilidades conocidas en paquetes de terceros.- Manejo Seguro de Secretos: Asegurar que los secretos (claves API, contraseñas de BD, secretos JWT) se gestionen de forma segura (usando
@nestjs/config, variables de entorno, vaults) y nunca se expongan en el código fuente ni en logs.- HTTPS: Configurar la aplicación para que se ejecute exclusivamente sobre HTTPS en producción.
Contexto y Justificación
La seguridad es una preocupación transversal. Más allá de la validación y autorización básicas, existen otros vectores de ataque comunes contra aplicaciones web. Implementar medidas como Helmet, Rate Limiting y mantener las dependencias actualizadas añade capas de defensa importantes para proteger la aplicación y sus usuarios.
Ejemplos y Contraejemplos
- Correcto (Aplicación de Helmet y Throttler):
// --- src/main.ts ---
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import helmet from 'helmet';
import { ThrottlerGuard } from '@nestjs/throttler';
import { APP_GUARD } from '@nestjs/core';
// ... otros imports, setup swagger, validation pipe ...
async function bootstrap() {
const app = await NestFactory.create(AppModule);
// ... validation pipe, swagger ...
// Aplica Helmet globalmente
app.use(helmet());
// Configura CORS si es necesario (antes o después de helmet)
app.enableCors(/* opciones de configuración */);
// Throttler se configura en AppModule y se aplica globalmente vía APP_GUARD
await app.listen(3000);
}
bootstrap();
// --- src/app.module.ts ---
import { Module } from '@nestjs/common';
import { ConfigModule } from '@nestjs/config';
import { ThrottlerModule, ThrottlerGuard } from '@nestjs/throttler';
import { APP_GUARD } from '@nestjs/core';
// ... otros imports
@Module({
imports: [
ConfigModule.forRoot({ isGlobal: true, /* ... */ }),
ThrottlerModule.forRoot([{
ttl: 60000, // Tiempo de vida en milisegundos (1 minuto)
limit: 10, // Límite de peticiones por ttl por IP
}]),
// ... otros módulos
],
providers: [
// Aplica ThrottlerGuard globalmente a todas las rutas
{
provide: APP_GUARD,
useClass: ThrottlerGuard,
},
// ... otros providers
],
})
export class AppModule {}
// --- Para Rate Limiting específico (Opcional) ---
import { Controller, Get, UseGuards } from '@nestjs/common';
import { Throttle } from '@nestjs/throttler';
@Controller('auth')
export class AuthController {
@Throttle({ default: { limit: 3, ttl: 60000 } }) // Sobrescribe el global para este endpoint
@Post('login')
login(/* ... */) {
// ...
}
} - Incorrecto: No usar Helmet. No implementar Rate Limiting en endpoints públicos o de autenticación. No revisar ni actualizar dependencias regularmente. Exponer secretos en el código o logs. Ejecutar en HTTP en producción.
Cuándo Aplicar
Siempre. Estas medidas de seguridad básicas (Helmet, Rate Limiting, gestión de dependencias, HTTPS) son obligatorias para cualquier aplicación en producción.
Cuándo Evitar o Flexibilizar
Nunca se deben omitir estas prácticas de seguridad fundamentales. La configuración específica (ej. límites de Rate Limiting) puede ajustarse según las necesidades, pero la implementación debe existir.