5-6-API -web-router

 Vamos a integrar express.Router() en tu ejemplo completo (web + API) manteniendo exactamente la misma funcionalidad, sin CSS adicional y de forma sencilla. La estructura será:

text
mi-app/
├── app.js
├── routes/
│   ├── webRoutes.js
│   └── apiRoutes.js
├── models/
│   └── productoModel.js
└── package.json

Paso 1: Crear el modelo (models/productoModel.js)

Centralizamos el arreglo de productos y las operaciones básicas.

javascript
// models/productoModel.js
let productos = [
  { id: 1, nombre: 'Laptop', precio: 1000 },
  { id: 2, nombre: 'Mouse', precio: 25 },
  { id: 3, nombre: 'Teclado', precio: 50 }
];

const getAll = () => productos;

const getById = (id) => productos.find(p => p.id === id);

const create = (nombre, precio) => {
  const nuevoId = productos.length > 0 ? Math.max(...productos.map(p => p.id)) + 1 : 1;
  const nuevoProducto = { id: nuevoId, nombre, precio: parseFloat(precio) };
  productos.push(nuevoProducto);
  return nuevoProducto;
};

module.exports = { getAll, getById, create };

Paso 2: Crear el router para la interfaz web (routes/webRoutes.js)

Aquí van todas las rutas que responden con HTML.

javascript
// routes/webRoutes.js
const express = require('express');
const router = express.Router();
const productoModel = require('../models/productoModel');

// WEB: Mostrar todos los productos (lista HTML)
router.get('/', (req, res) => {
  const productos = productoModel.getAll();
  let listaHTML = '';
  for (let p of productos) {
    listaHTML += `
      <li>
        <strong>${p.nombre}</strong> - $${p.precio}
        (<a href="/productos/${p.id}">Ver detalles</a>)
      </li>
    `;
  }

  res.send(`
    <!DOCTYPE html>
    <html>
    <head>
      <title>Productos</title>
      <style>body{font-family:Arial;margin:30px;} li{margin:10px 0;}</style>
    </head>
    <body>
      <h1>📦 Lista de productos</h1>
      <ul>${listaHTML}</ul>
      <hr>
      <h2>➕ Agregar producto</h2>
      <form action="/productos" method="POST">
        <input type="text" name="nombre" placeholder="Nombre" required>
        <input type="number" step="1" name="precio" placeholder="Precio" required>
        <button type="submit">Crear</button>
      </form>
      <hr>
      <p><strong>🔗 Endpoints API (JSON):</strong> <a href="/api/productos">/api/productos</a></p>
    </body>
    </html>
  `);
});

// WEB: Mostrar un solo producto (detalle HTML)
router.get('/productos/:id', (req, res) => {
  const id = parseInt(req.params.id);
  const prod = productoModel.getById(id);
  if (!prod) {
    return res.status(404).send('<h1>404 - Producto no encontrado</h1><a href="/">Volver</a>');
  }
  res.send(`
    <!DOCTYPE html>
    <html>
    <head>
      <title>${prod.nombre}</title>
      <style>body{font-family:Arial;margin:30px;}</style>
    </head>
    <body>
      <h1>📄 Detalle del producto</h1>
      <p><strong>ID:</strong> ${prod.id}</p>
      <p><strong>Nombre:</strong> ${prod.nombre}</p>
      <p><strong>Precio:</strong> $${prod.precio}</p>
      <a href="/">← Volver al listado</a>
    </body>
    </html>
  `);
});

// WEB: Crear producto (recibe POST del formulario y redirige)
router.post('/productos', (req, res) => {
  const { nombre, precio } = req.body;
  if (!nombre || !precio) {
    return res.status(400).send('<h1>Error: faltan datos</h1><a href="/">Volver</a>');
  }
  productoModel.create(nombre, precio);
  res.redirect('/');
});

module.exports = router;

Paso 3: Crear el router para la API REST (routes/apiRoutes.js)

Rutas con prefijo /api que devuelven JSON.

javascript
// routes/apiRoutes.js
const express = require('express');
const router = express.Router();
const productoModel = require('../models/productoModel');

// API: Obtener todos los productos (JSON)
router.get('/productos', (req, res) => {
  const productos = productoModel.getAll();
  res.json(productos);
});

// API: Obtener un producto por ID (JSON)
router.get('/productos/:id', (req, res) => {
  const id = parseInt(req.params.id);
  const prod = productoModel.getById(id);
  if (!prod) {
    return res.status(404).json({ error: 'Producto no encontrado' });
  }
  res.json(prod);
});

// API: Crear un nuevo producto (JSON)
router.post('/productos', (req, res) => {
  const { nombre, precio } = req.body;
  if (!nombre || typeof precio !== 'number') {
    return res.status(400).json({ error: 'Se requiere nombre y precio (número)' });
  }
  const nuevoProducto = productoModel.create(nombre, precio);
  res.status(201).json(nuevoProducto);
});

module.exports = router;

Paso 4: Archivo principal (app.js) – limpio y usando routers

javascript
// app.js
const express = require('express');
const app = express();
const PORT = 3000;

// Middlewares globales
app.use(express.json());                      // Para leer JSON (API)
app.use(express.urlencoded({ extended: true })); // Para leer formularios web

// Importar routers
const webRoutes = require('./routes/webRoutes');
const apiRoutes = require('./routes/apiRoutes');

// Montar routers
app.use('/', webRoutes);      // Todas las rutas web (HTML) sin prefijo
app.use('/api', apiRoutes);   // Todas las rutas API con prefijo /api

// Iniciar servidor
app.listen(PORT, () => {
  console.log(`✅ Servidor funcionando en http://localhost:${PORT}`);
  console.log('🌐 Interfaz web:');
  console.log('   - Lista de productos: http://localhost:3000/');
  console.log('   - Detalle de producto: http://localhost:3000/productos/1');
  console.log('🔌 API JSON:');
  console.log('   - GET  /api/productos       → Todos los productos');
  console.log('   - GET  /api/productos/:id   → Un producto');
  console.log('   - POST /api/productos       → Crear producto (enviar JSON)');
});

¿Cómo queda la estructura final?

text
mi-app/
├── app.js
├── models/
│   └── productoModel.js
├── routes/
│   ├── webRoutes.js
│   └── apiRoutes.js
└── package.json

Explicación del uso de Router para los alumnos

  • express.Router() crea un mini-manejador de rutas independiente.

  • webRoutes contiene todas las rutas que devuelven HTML (las originales sin /api).

  • apiRoutes contiene las rutas que devuelven JSON, todas bajo el prefijo /api.

  • En app.js montamos cada router con app.use(prefijo, router). Así las rutas se organizan por responsabilidad y el archivo principal queda muy limpio.

  • El modelo (productoModel.js) se comparte entre ambos routers, evitando duplicar la lógica de datos.

Beneficios didácticos

  • Separa claramente la interfaz web de la API REST.

  • Muestra cómo reutilizar código (el modelo) en diferentes partes de la aplicación.

  • Prepara a los alumnos para aplicaciones más grandes donde se necesita organización.

  • No cambia absolutamente nada en el comportamiento original, solo en la estructura del código.

Cómo probarlo

  1. Crear las carpetas y archivos con el contenido exacto de arriba.

  2. Instalar Express: npm init -y && npm install express

  3. Ejecutar: node app.js

  4. Abrir http://localhost:3000 (web) y también probar http://localhost:3000/api/productos (JSON).

Todo funcionará exactamente igual que antes, pero ahora con una arquitectura modular y usando express.Router()

Comentarios

Entradas más populares de este blog

Cómo Iniciar un Proyecto Node.js

8-Template Engines

5-Express--Curso de Node.js#05 Introducción a Express.js