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:

mkdir restful-api
cd restful-api

Inicializa un nuevo proyecto Node.js:

npm init -y

Paso 2: Instalar Dependencias

Instala Express.js y otras dependencias necesarias:

npm install express body-parser mongoose

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:

npm install express-validator

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:

npm install jsonwebtoken bcryptjs

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

  1. GET /users: Obtén todos los usuarios.
  2. POST /users: Crea un nuevo usuario.
  3. GET /users/:id: Obtén un usuario por ID.
  4. PUT /users/:id: Actualiza un usuario.
  5. DELETE /users/:id: Elimina un usuario.

Pruebas Automatizadas

Instala Mocha y Chai:

npm install mocha chai supertest --save-dev

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

Módulo 5: NPM y Gestión de Paquetes

Módulo 6: Framework Express.js

Módulo 7: Bases de Datos y ORMs

Módulo 8: Autenticación y Autorización

Módulo 9: Pruebas y Depuración

Módulo 10: Temas Avanzados

Módulo 11: Despliegue y DevOps

Módulo 12: Proyectos del Mundo Real

© Copyright 2024. Todos los derechos reservados