En este módulo, aprenderás a construir APIs RESTful utilizando Node.js. Las APIs RESTful son una forma estándar de crear servicios web que permiten la comunicación entre diferentes aplicaciones a través de HTTP. Este módulo cubrirá los conceptos básicos de REST, cómo estructurar una API, y cómo implementar las operaciones CRUD (Crear, Leer, Actualizar, Eliminar) utilizando Node.js y Express.js.
Contenido
Conceptos Básicos de REST
¿Qué es REST?
REST (Representational State Transfer) es un estilo de arquitectura para diseñar servicios web. Los principios básicos de REST incluyen:
- Recursos: Todo en REST es un recurso, que puede ser identificado por una URL.
- Métodos HTTP: Los métodos HTTP (GET, POST, PUT, DELETE) se utilizan para realizar operaciones sobre los recursos.
- Stateless: Cada solicitud del cliente al servidor debe contener toda la información necesaria para entender y procesar la solicitud.
- Representaciones: Los recursos pueden ser representados en diferentes formatos, como JSON o XML.
Métodos HTTP
Método | Descripción | Ejemplo de Uso |
---|---|---|
GET | Obtener un recurso | GET /api/users |
POST | Crear un nuevo recurso | POST /api/users |
PUT | Actualizar un recurso | PUT /api/users/:id |
DELETE | Eliminar un recurso | DELETE /api/users/:id |
Configuración del Proyecto
Paso 1: Crear un Proyecto Node.js
Primero, crea un nuevo directorio para tu proyecto y navega a él:
Inicializa un nuevo proyecto Node.js:
Paso 2: Instalar Dependencias
Instala Express.js y otras dependencias necesarias:
Paso 3: Configurar el Servidor
Crea un archivo server.js
y configura el servidor básico:
const express = require('express'); const bodyParser = require('body-parser'); const app = express(); const PORT = process.env.PORT || 3000; app.use(bodyParser.json()); app.get('/', (req, res) => { res.send('API RESTful con Node.js y Express'); }); app.listen(PORT, () => { console.log(`Servidor corriendo en el puerto ${PORT}`); });
Creación de Rutas y Controladores
Paso 1: Definir Rutas
Crea un directorio routes
y un archivo userRoutes.js
:
const express = require('express'); const router = express.Router(); const userController = require('../controllers/userController'); router.get('/users', userController.getAllUsers); router.post('/users', userController.createUser); router.get('/users/:id', userController.getUserById); router.put('/users/:id', userController.updateUser); router.delete('/users/:id', userController.deleteUser); module.exports = router;
Paso 2: Crear Controladores
Crea un directorio controllers
y un archivo userController.js
:
const User = require('../models/user'); exports.getAllUsers = (req, res) => { // Lógica para obtener todos los usuarios }; exports.createUser = (req, res) => { // Lógica para crear un nuevo usuario }; exports.getUserById = (req, res) => { // Lógica para obtener un usuario por ID }; exports.updateUser = (req, res) => { // Lógica para actualizar un usuario }; exports.deleteUser = (req, res) => { // Lógica para eliminar un usuario };
Implementación de Operaciones CRUD
Paso 1: Crear el Modelo de Usuario
Crea un directorio models
y un archivo user.js
:
const mongoose = require('mongoose'); const userSchema = new mongoose.Schema({ name: { type: String, required: true }, email: { type: String, required: true, unique: true }, password: { type: String, required: true } }); module.exports = mongoose.model('User', userSchema);
Paso 2: Implementar Controladores
Actualiza userController.js
con la lógica CRUD:
const User = require('../models/user'); exports.getAllUsers = async (req, res) => { try { const users = await User.find(); res.status(200).json(users); } catch (error) { res.status(500).json({ message: error.message }); } }; exports.createUser = async (req, res) => { const user = new User({ name: req.body.name, email: req.body.email, password: req.body.password }); try { const newUser = await user.save(); res.status(201).json(newUser); } catch (error) { res.status(400).json({ message: error.message }); } }; exports.getUserById = async (req, res) => { try { const user = await User.findById(req.params.id); if (user == null) { return res.status(404).json({ message: 'Usuario no encontrado' }); } res.status(200).json(user); } catch (error) { res.status(500).json({ message: error.message }); } }; exports.updateUser = async (req, res) => { try { const user = await User.findById(req.params.id); if (user == null) { return res.status(404).json({ message: 'Usuario no encontrado' }); } if (req.body.name != null) { user.name = req.body.name; } if (req.body.email != null) { user.email = req.body.email; } if (req.body.password != null) { user.password = req.body.password; } const updatedUser = await user.save(); res.status(200).json(updatedUser); } catch (error) { res.status(400).json({ message: error.message }); } }; exports.deleteUser = async (req, res) => { try { const user = await User.findById(req.params.id); if (user == null) { return res.status(404).json({ message: 'Usuario no encontrado' }); } await user.remove(); res.status(200).json({ message: 'Usuario eliminado' }); } catch (error) { res.status(500).json({ message: error.message }); } };
Manejo de Errores y Validación
Validación de Datos
Para validar los datos de entrada, puedes usar bibliotecas como express-validator
. Instálala:
Actualiza userController.js
para incluir validaciones:
const { body, validationResult } = require('express-validator'); exports.createUser = [ body('name').notEmpty().withMessage('El nombre es requerido'), body('email').isEmail().withMessage('Debe ser un correo electrónico válido'), body('password').isLength({ min: 6 }).withMessage('La contraseña debe tener al menos 6 caracteres'), async (req, res) => { const errors = validationResult(req); if (!errors.isEmpty()) { return res.status(400).json({ errors: errors.array() }); } const user = new User({ name: req.body.name, email: req.body.email, password: req.body.password }); try { const newUser = await user.save(); res.status(201).json(newUser); } catch (error) { res.status(400).json({ message: error.message }); } } ];
Autenticación y Autorización
Para la autenticación, puedes usar JWT (JSON Web Tokens). Instala las dependencias necesarias:
Actualiza userController.js
para incluir la lógica de autenticación:
const jwt = require('jsonwebtoken'); const bcrypt = require('bcryptjs'); exports.login = async (req, res) => { const { email, password } = req.body; try { const user = await User.findOne({ email }); if (!user) { return res.status(400).json({ message: 'Correo o contraseña incorrectos' }); } const isMatch = await bcrypt.compare(password, user.password); if (!isMatch) { return res.status(400).json({ message: 'Correo o contraseña incorrectos' }); } const token = jwt.sign({ id: user._id }, process.env.JWT_SECRET, { expiresIn: '1h' }); res.status(200).json({ token }); } catch (error) { res.status(500).json({ message: error.message }); } };
Pruebas de la API
Para probar la API, puedes usar herramientas como Postman o escribir pruebas automatizadas con Mocha y Chai.
Pruebas con Postman
- GET /users: Obtén todos los usuarios.
- POST /users: Crea un nuevo usuario.
- GET /users/:id: Obtén un usuario por ID.
- PUT /users/:id: Actualiza un usuario.
- DELETE /users/:id: Elimina un usuario.
Pruebas Automatizadas
Instala Mocha y Chai:
Crea un archivo test/user.test.js
y escribe pruebas:
const request = require('supertest'); const app = require('../server'); const expect = require('chai').expect; describe('GET /users', () => { it('debería obtener todos los usuarios', (done) => { request(app) .get('/users') .end((err, res) => { expect(res.status).to.equal(200); expect(res.body).to.be.an('array'); done(); }); }); });
Conclusión
En este módulo, has aprendido a construir una API RESTful utilizando Node.js y Express.js. Has cubierto los conceptos básicos de REST, cómo configurar un proyecto, crear rutas y controladores, implementar operaciones CRUD, manejar errores y validaciones, y realizar pruebas de la API. Con estos conocimientos, estás preparado para construir APIs robustas y escalables.
En el siguiente módulo, exploraremos cómo integrar GraphQL con Node.js para crear APIs más flexibles y eficientes. ¡Sigue adelante!
Curso de Node.js
Módulo 1: Introducción a Node.js
Módulo 2: Conceptos Básicos
Módulo 3: Sistema de Archivos y E/S
Módulo 4: HTTP y Servidores Web
- Creando un Servidor HTTP Simple
- Manejo de Solicitudes y Respuestas
- Sirviendo Archivos Estáticos
- Enrutamiento
Módulo 5: NPM y Gestión de Paquetes
- Introducción a NPM
- Instalación y Uso de Paquetes
- Creación y Publicación de Paquetes
- Versionado Semántico
Módulo 6: Framework Express.js
- Introducción a Express.js
- Configuración de una Aplicación Express
- Middleware
- Enrutamiento en Express
- Manejo de Errores
Módulo 7: Bases de Datos y ORMs
- Introducción a las Bases de Datos
- Usando MongoDB con Mongoose
- Usando Bases de Datos SQL con Sequelize
- Operaciones CRUD
Módulo 8: Autenticación y Autorización
- Introducción a la Autenticación
- Usando Passport.js
- Autenticación JWT
- Control de Acceso Basado en Roles
Módulo 9: Pruebas y Depuración
- Introducción a las Pruebas
- Pruebas Unitarias con Mocha y Chai
- Pruebas de Integración
- Depuración de Aplicaciones Node.js
Módulo 10: Temas Avanzados
- Módulo Cluster
- Hilos de Trabajo
- Optimización del Rendimiento
- Construcción de APIs RESTful
- GraphQL con Node.js
Módulo 11: Despliegue y DevOps
- Variables de Entorno
- Usando PM2 para la Gestión de Procesos
- Desplegando en Heroku
- Integración y Despliegue Continuos