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
