This post is also available in: English

Este tutorial de ExpressJS supone que ha instalado Node.JS y MongoDB. Aquí hay un enlace a la repo de github.

Express es un framework impresionante para crear APIs web rápidas para interactuar con tu SPA y porque también está en JavaScript, tu base decódigo puede ser desarrollado en 1 idioma. La facilita el uso de todas las mismas herramientas familiar si se está integrando con React JS o Angular.

En este tutorial, crearemos una simple API de blogs que devolverá una lista de mensajes de blog al usuario. En posts posteriores, cubriremos JWT autenticación y relaciones de usuario con MongoDB pero por ahora, nos centraremos en CRUD básico.

Configuración del proyecto con NPM

Para crear nuestra aplicación, primero vamos a tener que configurar la configuración de la NPM y asegurarnos de que especificamos que nuestro proyecto utiliza la sintaxis ES6.

Crear una carpeta de proyecto en la línea de comandos ejecutando

mkdir ExpressAPIBlog && cd ExpressAPIBlog

Ahora que está en el directorio, cree un package.json y agregue dependencias de dev

npm init
npm install --save-dev babel-cli babel-preset-stage-0 babel-preset-env

Esto le permitirá compilar su código ES6 a ES5 para que sea entendido por Express.JS y Node.

npm install body-parser cuid express limax mongoose sanatize-html
Ahora que todo está instalado, cree un archivo llamado Server.js
import express from 'express';
import bodyParser from 'body-parser';
let app = express();
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({
    extended: false
}));
app.get('/', (req, res) => res.send('Hello World!'));

app.listen(3005, () => {
    console.log('server started - 3005');
});

A continuación, añada una secuencia de comandos al archivo package.json para ejecutar el servidor

"scripts": {
    "start": "babel-node server.js --presets env",
    "test": "echo "Error: no test specified" && exit 1"
  },

Configuración de base de datos con Mongoose

Ahora que Express está funcionando, vamos a configurar una conexión de base de datos.

En primer lugar, vamos a crear un archivo de configuración que especifique nuestra conexión a la instancia de la base de datos
mkdir config && touch config/index.js

Abra el archivo y agregue el número de puerto y la cadena de conexión de base de datos.

export default {
    "port": 3005,
    "mongoUrl": "mongodb://localhost:27017/express-api-blog",
    "bodyLimit": "100kb"
}

Una vez hecho esto, crea un archivo de base de datos que conecta tu aplicación Express a Mongo dB.

mkdir db && touch db/connect.js
import mongoose from 'mongoose';
import config from '../config/index';

mongoose.Promise = global.Promise;

const connectToDb = async () => {
    try {
        await mongoose.connect(config.mongoUrl, { useMongoClient: true });
        
    }
    catch (err) {
        
      console.log(err);
    }
}

export default connectToDb;

Aquí se crea una función asincrónica que intenta conectarse a la dB y si falla, consuela el error.

Creación del modelo

A continuación tenemos que crear el modelo para el post. Esto representa cada entrada que entra en la base de datos.

mkdir models && touch post.js

Dentro de este modelo vamos a añadir un título junto con el contenido de post, una fecha en la que se creó el post, una Slug que se generará basándose en el título y un cuid que es un número de identificación. A pesar de que todos los documentos mangosta tienen un campo de identificación por defecto, cuid es otra gran manera de tener IDs resistentes a colisiones

import mongoose from 'mongoose';
const Schema = mongoose.Schema;

const postSchema = new Schema({
    title: { type: 'String', required: true },
    content: { type: 'String', required: true },
    slug: { type: 'String', required: true },
    cuid: { type: 'String', required: true },
    dateAdded: { type: 'Date', default: Date.now, required: true },
});

let Post = mongoose.model('Post', postSchema);

export default Post;

Acciones del controlador Express

Ahora que tenemos nuestra configuración de base de datos y el modelo que quisiéramos utilizar para poblar la base de datos, ahora debemos encontrar una manera de permitir al usuario enviar peticiones a la API para crear nuevos mensajes. Podríamos colocar todas las solicitudes dentro del archivo Server. js pero es mucho más limpio crear un archivo controlador.

mkdir controllers && touch controllers/post.controller.js

Dentro de este controlador vamos a necesitar 5 funciones CRUD. Una get All, Get by ID, Create, Update y Delete.

import Post from '../models/post';
import cuid from 'cuid';
import slug from 'limax';
import sanitizeHtml from 'sanitize-html';

const PostController = {};

Hemos creado un objeto controlador para que sea fácil exportar todas las funciones que vamos a crear.

La primera función será en realidad la función getAll ().
PostController.getAll = async (req, res) => {
    try{
        await Post.find().sort('-dateAdded').exec((err, posts) => {
            if (err) {
                res.status(500).send(err);
            }
            res.json({ posts });
        });
    }
    catch(err){
        res.send(err);
    }
}

Esta función toma la petición, intenta la función y devuelve una lista de mensajes o un Err dependiendo de dónde se produce el error.

Entonces tenemos la función getPost. Esto encuentra el mensaje por su cuid y devuelve el post si existe.

PostController.getPost = async (req, res) => {
    try{
        Post.findOne({ cuid: req.params.cuid }).exec((err, post) => {
            if (err) {
                res.status(500).send(err);
            }
            res.json({ post });
        });
    }
    catch(err){

    }
}

A continuación, tenemos la función addPost. Esto comprueba si el título o el contenido no está presente, crea el mensaje, desinfecta el contenido y, a continuación, guarda el mensaje en la base de datos.

PostController.addPost = async (req, res) => {
    try {
        if (!req.body.post.title || !req.body.post.content) {
            res.status(403).end();
        }

        const newPost = new Post(req.body.post);

        // Sanitize inputs
        newPost.title = sanitizeHtml(newPost.title);
        newPost.content = sanitizeHtml(newPost.body);

        newPost.slug = slug(newPost.title.toLowerCase(), { lowercase: true });
        newPost.cuid = cuid();

        newPost.save((err, saved) => {
            if (err) {
                res.status(500).send(err);
            }
            res.json({ post: saved });
        });
    }
    catch (err) {
        console.log(err);
    }
}

UpdatePost es muy similar a addPost excepto que encuentra el mensaje por su cuid, a continuación, actualiza los campos.

PostController.updatePost = async (req, res) => {
    try {
        if (!req.body.post.title || !req.body.post.content) {
            res.status(403).end();
        }
        Post.findOne({ cuid: req.params.cuid }).exec((err, post) => {
            // Handle database errors
            if (err) {
                res.status(500).send(err);
            } else {
                post.title = req.body.post.title || post.title;
                post.content = req.body.post.content || post.content;
                console.log('Post about to be saved');
                // Save 
                post.save((err, saved) => {
                    if (err) {
                        res.status(500).send(err)
                    }
                    res.json({ post: saved });
                });
            }
        });
    }
    catch (err) {
        console.log(err);
    }
}

Para la solicitud de DELETE, tenemos deletePost. Esto toma el cuid y borra el post con ese ID. Al final, también exportamos el controlador.

PostController.deletePost = async (req, res) => {
    try {
        Post.findOne({ cuid: req.params.cuid }).exec((err, post) => {
            if (err) {
                res.status(500).send(err);
            }

            post.remove(() => {
                res.status(200).end();
            });
        });
    }
    catch (err) {
        console.log(err);
    }
}

export default PostController;

Express Routing

A pesar de que ahora tenemos nuestro controlador configurado, vamos a necesitar una manera de acceder a las rutas en nuestro controlador. Esto se puede hacer fácilmente creando un archivo de enrutamiento. En la línea de comandos ejecutar

mkdir routes && touch routes/posts.routes.js

Dentro de su archivo Server. js, agregue

import posts from './routes/posts.routes';


app.use('/api', posts);

Ahora abra el archivo posts.routes e importe el router Express y el controlador.

import { Router } from 'express';
import PostController from '../controllers/post.controller';
const router = new Router();

Esto le permitirá asignar las solicitudes GET, post, Put y Delete a los métodos del controlador.

// Get all Posts
router.get('/posts', (req, res) => {
    PostController.getAll(req, res);
});

// Get one post by cuid
router.get('/posts/:cuid', (req, res) =>{
    PostController.getPost(req,res);
});

// Add a new Post
router.post('/posts', (req, res) => {
    PostController.addPost(req, res);
});

router.put('/posts/:cuid', (req, res) => {
    PostController.updatePost(req, res);
});

// Delete a post by cuid
router.delete('/posts/:cuid', (req, res) => {
    PostController.deletePost(req, res);
});
export default router;

Una vez hecho esto, debemos estar listos para probar nuestra API.

Probando rutas API con Insomnia

Comencemos creando algunos posts. Ejecutar el servidor con
npm run-script start

y crear algunos posts con

Express Blog API Create

Express Blog API Create

Hacer esto varias veces y luego hacer una solicitud GET para devolver todos los mensajes

Get Request Express Blog API

Get Request Express Blog API

También puede utilizar una herramienta como Compass para ver todos sus documentos MongoDB

MongoCompass Expres Blog API

MongoCompass Expres Blog API

Ahora vamos a probar a probar a conseguir un mensaje por su ID.
GetByCUID Express Blog API

GetByCUID Express Blog API

También pasando el cuid y el contenido modificado, podemos actualizar el post.

Put Request Blog API Express

Put Request Blog API Express

Finalmente tenemos la solicitud de DELETE. Esto se puede hacer sólo pasando por el cuid.

Delete-Request-Express-Blog-API

Delete-Request-Express-Blog-API

Conclusion

Actualmente la configuración de una API de REST con ES6 actualmente requiere una gran cantidad de herramientas para compilar el JavaScript, pero ofrece la capacidad de escribir la limpieza, código más mantenible. En posts posteriores, vamos a discutir la adición de administración de usuarios y la autenticación a la API, así como la construcción de un cliente reaccionar y angular. Para estar al tanto del proyecto, visite el enlace al repositorio de github.

 

Codebrains Newsletter

Get weekly dev news and tutorials.

Powered by ConvertKit

This post is also available in: English