Nest: Controladores

Aprende a crear y organizar controladores en NestJS para manejar peticiones HTTP y construir APIs modulares y eficientes.

Aprende Nest GRATIS y certifícate

Controladores en Nest

Los controladores constituyen el punto de entrada principal para las peticiones HTTP en una aplicación Nest. Su función primordial es recibir solicitudes del cliente, procesarlas y devolver las respuestas correspondientes. En el contexto de Nest, los controladores actúan como la capa de presentación que define los endpoints de nuestra API.

Fundamentos de los controladores

Un controlador en Nest es una clase TypeScript decorada con @Controller() que agrupa rutas relacionadas y define cómo la aplicación responde a diferentes peticiones HTTP. Esta aproximación permite organizar el código de manera modular y mantener una separación clara de responsabilidades.

import { Controller, Get } from '@nestjs/common';

@Controller('usuarios')
export class UsuariosController {
  @Get()
  obtenerTodos() {
    return 'Esta acción devuelve todos los usuarios';
  }
}

El decorador @Controller() acepta un prefijo de ruta opcional que se aplica a todas las rutas definidas dentro del controlador. En el ejemplo anterior, todas las rutas tendrán el prefijo /usuarios.

Métodos HTTP y decoradores de ruta

Nest proporciona decoradores específicos para cada método HTTP, permitiendo una definición clara y expresiva de los endpoints:

@Controller('productos')
export class ProductosController {
  @Get()
  listar() {
    return 'Obtener todos los productos';
  }

  @Post()
  crear() {
    return 'Crear un nuevo producto';
  }

  @Put(':id')
  actualizar() {
    return 'Actualizar producto completo';
  }

  @Patch(':id')
  actualizarParcial() {
    return 'Actualizar producto parcialmente';
  }

  @Delete(':id')
  eliminar() {
    return 'Eliminar producto';
  }
}

Los parámetros de ruta se definen utilizando la sintaxis :parametro, similar a Express. Estos parámetros pueden ser capturados y utilizados dentro de los métodos del controlador.

Captura de datos de la petición

Los controladores necesitan acceder a diferentes partes de la petición HTTP. Nest proporciona decoradores especializados para extraer información específica:

Parámetros de ruta:

@Get(':id')
obtenerPorId(@Param('id') id: string) {
  return `Producto con ID: ${id}`;
}

@Get(':categoria/:id')
obtenerPorCategoriaYId(
  @Param('categoria') categoria: string,
  @Param('id') id: string
) {
  return `Producto ${id} de la categoría ${categoria}`;
}

Parámetros de consulta:

@Get()
buscar(
  @Query('nombre') nombre?: string,
  @Query('precio') precio?: number
) {
  return `Buscando productos: nombre=${nombre}, precio=${precio}`;
}

Cuerpo de la petición:

@Post()
crear(@Body() datosProducto: any) {
  return `Creando producto: ${JSON.stringify(datosProducto)}`;
}

@Post()
crearConValidacion(@Body('nombre') nombre: string) {
  return `Creando producto con nombre: ${nombre}`;
}

Manejo de respuestas HTTP

Por defecto, Nest devuelve automáticamente el código de estado 200 para GET y 201 para POST. Sin embargo, es posible personalizar tanto el código de estado como las cabeceras de respuesta:

import { Controller, Post, HttpCode, Header, Res } from '@nestjs/common';
import { Response } from 'express';

@Controller('api')
export class ApiController {
  @Post()
  @HttpCode(204)
  @Header('Cache-Control', 'none')
  crear() {
    return 'Creado sin contenido';
  }

  @Get('archivo')
  descargar(@Res() respuesta: Response) {
    respuesta.download('./archivo.pdf');
  }
}

El decorador @HttpCode() permite especificar el código de estado de respuesta, mientras que @Header() establece cabeceras personalizadas. Para casos más complejos, es posible inyectar directamente el objeto Response de Express.

Organización y estructura

Los controladores deben seguir el principio de responsabilidad única, agrupando únicamente rutas relacionadas con una entidad o funcionalidad específica. Una estructura típica incluye:

@Controller('tienda')
export class TiendaController {
  // Rutas para listado y búsqueda
  @Get()
  listarProductos(@Query() filtros: any) {
    // Lógica de listado
  }

  @Get('buscar')
  buscarProductos(@Query('termino') termino: string) {
    // Lógica de búsqueda
  }

  // Rutas para operaciones CRUD
  @Get(':id')
  obtenerProducto(@Param('id') id: string) {
    // Lógica de obtención
  }

  @Post()
  crearProducto(@Body() producto: any) {
    // Lógica de creación
  }
}

Integración con servicios

Los controladores no deben contener lógica de negocio compleja. Su responsabilidad se limita a recibir peticiones, delegar el procesamiento a servicios especializados y devolver respuestas:

import { Injectable } from '@nestjs/common';

@Injectable()
export class ProductosService {
  private productos = [];

  obtenerTodos() {
    return this.productos;
  }

  crear(producto: any) {
    this.productos.push(producto);
    return producto;
  }
}

@Controller('productos')
export class ProductosController {
  constructor(private readonly productosService: ProductosService) {}

  @Get()
  listar() {
    return this.productosService.obtenerTodos();
  }

  @Post()
  crear(@Body() producto: any) {
    return this.productosService.crear(producto);
  }
}

Esta separación de responsabilidades facilita el mantenimiento, testing y reutilización del código, siguiendo los principios de arquitectura limpia que promueve Nest.

Empezar curso de Nest

Lecciones de este módulo de Nest

Lecciones de programación del módulo Controladores del curso de Nest.

Ejercicios de programación en este módulo de Nest

Evalúa tus conocimientos en Controladores con ejercicios de programación Controladores de tipo Test, Puzzle, Código y Proyecto con VSCode.