Tutorial: Crear API RESTful utilizando Node.js + Express.js + MongoDB

| 2016-06-23 | 10 Comentarios »

El primer paso para implementar un proyecto moderno es la construcción de un API REST que podemos consumir desde una aplicación web o móvil.

nodejs-express-mongo En el presente tutorial utilizaré las tecnologías Node.js y MongoDB como base de datos para crear un API RESTful. Como framework para Node.js, utilizaré Express.js (versión 4) con MongoDB.

Una API RESTful es un conjunto de operaciones bien definidas que se aplican a todos los recursos de información: HTTP en sí define un conjunto pequeño de operaciones, las más importantes son POST, GET, PUT y DELETE. Con frecuencia estas operaciones se equiparan a las operaciones CRUD en bases de datos (ABMC en castellano: crear,leer,actualizar,borrar) que se requieren para la persistencia de datos, aunque POST no encaja exactamente en este esquema.

1- Crear proyecto e inicializarlo (Para obtener más información y ayuda con este paso ingresar a: Link)

$ mkdir nodejs-apirest
$ cd nodejs-apirest
$ npm init
$ npm install express

El primer código que necesitamos modificar en una aplicación basada en Node.js es el archivo package.json. Éste archivo nos indica que dependencias vamos a utilizar en ella. Este archivo va en el directorio raíz de la aplicación:

{
 "name": "nodejs-apirest",
 "version": "1.0.0",
 "dependencies": {
 "body-parser": "~1.13.2",
 "express": "~4.13.1",
 "method-override": "^2.1.2",
 "mongoose": "~3.6.11"
 }
}

Posteriormente debemos de descargar las dependencias:

$ npm install

2- Servidor Node.js

Ahora deben de crear el archivo app.js (en la raíz del proyecto) y dejarlo así:

var express = require('express');
var bodyParser = require('body-parser');
var mongoose = require('mongoose');
var methodOverride = require("method-override");
var app = express();

// Middlewares
app.use(bodyParser.urlencoded({ extended: false })); 
app.use(bodyParser.json()); 
app.use(methodOverride());

var router = express.Router();

// Index
router.get('/', function(req, res) { 
 res.send("Hola Mundo - www.programacion.com.py");
});

app.use(router);

// Start server
app.listen(3000, function() {
 console.log("Node server running on http://localhost:3000");
});

Explicación de que hace el código:

-bodyParser: Permite parsear JSON.

-methodOverride: Permite implementar y personalizar métodos HTTP.

Para ejecutar dicho código sólo tienes que escribir en consola lo siguiente y abrir un navegador con la url http://localhost:3000

$ node app.js
nodejsapi

3- Crear modelo

Seguimos con la parte de la creación del modelo, utilizaremos Mongoose. Utilizaremos MongoDB: es la base de datos NoSQL líder y permite a las empresas ser más ágiles y escalables.

Para este tutorial crearemos una base de datos de clientes, para eso creamos el modelo cliente (models/client.js):

var mongoose = require('mongoose');
var Schema = mongoose.Schema;

var clientSchema = new Schema({ 
 name: { type: String },
 email: { type: String },
 genre: { type: String, enum: ['male', 'female'] }
});

module.exports = mongoose.model('Client', clientSchema);

Con esto ya podemos implementar la conexión a la base de datos en el archivo app.js añadiendo las siguientes líneas:

mongoose.connect('mongodb://localhost/clients', function(err, res) {
 if(err) throw err;
 console.log('Connected to Database');
});

Para que todo lo que está arriba funcione en nuestro entorno local, necesitamos tener instalado MongoDB, para eso ingresar a la: documentación oficial.

Ya tenemos todo configurado y listo para guardar y utilizar los datos, sólo nos queda crear las rutas que definirán las llamadas a la API.

3- Crear controlador

Seguimos con la parte de la creación del controlador (controllers/client.js):

var mongoose = require('mongoose');
var Client = mongoose.model('Client');

//GET - Return all registers
exports.findAll = function(req, res) {
 Client.find(function(err, clients) {
 if(err) res.send(500, err.message);
 console.log('GET /clients')
 res.status(200).jsonp(clients);
 });
};

//GET - Return a register with specified ID
exports.findById = function(req, res) {
 Client.findById(req.params.id, function(err, client) {
 if(err) return res.send(500, err.message);
 console.log('GET /clients/' + req.params.id);
 res.status(200).jsonp(client);
 });
};

//POST - Insert a new register
exports.add = function(req, res) {
 console.log('POST');
 console.log(req.body);
 var client = new Client({
 name: req.body.name,
 email: req.body.email,
 genre: req.body.genre
 });
 client.save(function(err, client) {
 if(err) return res.send(500, err.message);
 res.status(200).jsonp(client);
 });
};

//PUT - Update a register already exists
exports.update = function(req, res) {
 Client.findById(req.params.id, function(err, client) {
 client.name = req.body.name;
 client.email = req.body.email;
 client.genre = req.body.genre;
 client.save(function(err) {
 if(err) return res.send(500, err.message);
 res.status(200).jsonp(client);
 });
 });
};

//DELETE - Delete a register with specified ID
exports.delete = function(req, res) {
 Client.findById(req.params.id, function(err, client) {
 client.remove(function(err) {
 if(err) return res.send(500, err.message);
 res.json({ message: 'Successfully deleted' });
 });
 });
};

Ahora tenemos que unir estas funciones del controlador a las peticiones que serán nuestras llamadas desde el API. Para eso debemos de editar el archivo app.js y declaramos las rutas, el archivo queda así:

var express = require('express');
var bodyParser = require('body-parser');
var mongoose = require('mongoose');
var methodOverride = require("method-override");
var app = express();

// Connection to DB
mongoose.connect('mongodb://localhost/clients', function(err, res) {
 if(err) throw err;
 console.log('Connected to Database');
});

// Middlewares
app.use(bodyParser.urlencoded({ extended: false })); 
app.use(bodyParser.json()); 
app.use(methodOverride());

// Import Models and Controllers
var models = require('./models/client')(app, mongoose);
var ClientCtrl = require('./controllers/clients');

var router = express.Router();

// Index - Route
router.get('/', function(req, res) { 
 res.send("Hola Mundo - www.programacion.com.py");
});

app.use(router);

// API routes
var api = express.Router();

api.route('/clients') 
 .get(ClientCtrl.findAll)
 .post(ClientCtrl.add);

api.route('/clients/:id') 
 .get(ClientCtrl.findById)
 .put(ClientCtrl.update)
 .delete(ClientCtrl.delete);

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


// Start server
app.listen(3000, function() {
 console.log("Node server running on http://localhost:3000");
});

4- Probar

A continuación voy a utilizar una extensión de Google Chrome llamada Postman para probar el API.

Antes de probarlo, debemos tener mongodb y el servidor node.js de nuestra app corriendo. Una vez hecho esto introducimos los siguientes datos para hacer una llamada POST que almacene un registro en la base de datos.

Method: POST

URL: http://localhost:3000/api/clients

Body, utilizando "X-www-form-urlencoded":

Luego pulsamos send, el resultado debe ser el siguiente:

postmanbody

Ahora vamos a comprobar que se ha guardado correctamente, para eso podemos enviar un request GET, a la url: http://localhost:3000/api/clients, el resultado debe de ser:

postmanbody2

Como pueden observar hay un registro con el id 5846ace82d6973ec1c000006, podemos recuperar ese registro enviando un request GET, a la url: http://localhost:3000/api/clients/5846ace82d6973ec1c000006 , el resultado debe de ser:

postmanbody3

Ahora vamos a probar editar el registro con el id 5846ace82d6973ec1c000006, para eso enviamos un request PUT, a la url: http://localhost:3000/api/clients/5846ace82d6973ec1c000006, el resultado debe de ser:

postmanbody4

Por último vamos a probar borrar el registro con el id 5846ace82d6973ec1c000006, para eso enviamos un request DELETE, a la url: http://localhost:3000/api/clients/5846ace82d6973ec1c000006, el resultado debe de ser:

postmanbody5

Con esto tendríamos el funcionamiento básico de un API RESTful con Node.js y MongoDB. Como puedes ver es bastante sencillo ya que se utiliza Javascript, como lenguaje de servidor (Node), como formato de datos (JSON) y como base de datos (MongoDB).

Descargar proyecto completo:

github-logo

Acerca del autor: Rodrigo Paszniuk

Ingeniero Informático, amante de la tecnología, la música, el ciclismo y aprender cosas nuevas.

Posts Relacionados

  • twitter-card Tutorial: Autenticación de usuarios en Node.js con Facebook utilizando Passport
  • maxresdefault Tutorial: Autenticación basada en Token utilizando Node.js + Express.js + MongoDB
  • mean-stack-tutorial Tutorial: Crear una aplicación web utilizando MEAN
  • nodejs-and-express Generador de aplicaciones de Express.js

  • Julián Gutierrez

    Lo creé paso a paso y al hacer un get me devuelve algo de este estilo
    [{
    “_id”: “5844ddde2123083013000001”,
    “__v”: 0
    }, {
    “_id”: “5844e45deca6b88029000001”,
    “__v”: 0
    },
    aún descargando el que subiste a github tengo el mismo resultado, que puede ser??
    gracias!

    • Hola Julián, al momento de cargar los clientes subiste toda la información de los mismos?, es decir su nombre y email?, podrías también usar Robomongo para ver eso y estaré atento a tu respuesta! Saludos!

      • Julián Gutierrez

        Hola Rodrigo muchas gracias por responder tan rápido!!, al parecer ya encontré el error pero aún no sé como solucionarlo puse unos console log en el método que se encarga de insertar los datos y viene como indefinido el párametro req, tienes alguna idea sobre el problema? adjunto dos capturas de robomongo y el console.log.

        Los datos los inserte desde un clienteRest que instalé en el navegador!

        https://uploads.disquscdn.com/images/3caa4333039f06866b1a80f046fd4630de964e92bc879d8a6097a3a66a1941da.png
        https://uploads.disquscdn.com/images/7b5b6583cfa1baed58e5c415d65f3e1b393c3040ce230123b157e2b1d9f1ecfa.png

        Gracias!!

        • Para eso estamos Julián, te comento que estuve probando y he decidido cambiar una parte del tutorial (el punto 4) porque el request post utilizando “raw” no funcionaba correctamente en algunas ocasiones, te recomiendo que pruebes utilizando “X-www-form-urlencoded” con Postman.

          La ilustración: https://uploads.disquscdn.com/images/918c8dc9e0849eaea3d11ca4eeb7ab02e6b1a201ea273588c3896d8e15f53e1a.png

          Avísame si con eso se soluciona el problema que tenías 🙂

          • Julián Gutierrez

            Listo !! ya logré que funcionara haciendo las peticiones con el mismo cliente y marcando el “X-www-form-urlencoded”. Como dato adicional en la parte del post me arrojaba un error al consumirlo con Angular era algo así como “express deprecated res.send(status):” por lo que tuve que cambiar “res.send(500, err.message);” por “res.status(500).send(err.message);” y hacer la petición al servicio así
            $http({
            method: ‘POST’,
            url: ‘http://localhost:3000/api/clients’,
            headers: {‘Content-Type’: ‘application/x-www-form-urlencoded’},
            transformRequest: function(obj) {
            var str = [];
            for(var p in obj)
            str.push(encodeURIComponent(p) + “=” + encodeURIComponent(obj[p]));
            return str.join(“&”);
            },
            data: {“name”: “Daniela”,”email”: “Daniela@gmail.com”,”genre”: “female”}
            })
            .success(function (datos) {
            console.log(“Success”+datos)
            })
            .catch(function(datos){
            angular.forEach(datos,function(llave,valor){
            console.log(llave+” – – “+valor);
            });
            });
            Para que lo tengan en cuenta si alguien mas tiene ese problema al consumirlo con angular.

            Muchas gracias Rodrigo!!!

          • Excelente muchas gracias por compartir eso Julián, pronto estaré creando más tutoriales de este tipo y ya con lo último que es ES6.

            Saludos!!

  • milogus

    Tengo un problema, hice todo el tutorial, pero al momento de tratar de hacer cualquier prueba, nunca me devuelve nada, el Postman se queda “sending…” y nunca agrega nada, ni busca nada, en la consola no aparece ningún error y el mongoDB si esta corriendo.

    He bajado el ejemplo tal cual y después de agregar las dependencias y todo, sigue haciendo lo mismo (la petición no regresa nada, ni errores en consola).

    Que podría ser?

    • Hola milogus, me podrías adjuntar un screen?, quiero ver tu postman ya que puede ser que estás haciendo el request a un puerto equivocado o sino el puerto ya lo está usando otra aplicación.

      Probá nuevamente hacer un request GET a http://localhost:3000/api/clients o http://127.0.0.1:3000/api/clients. En el caso de que tengas otra aplicación corriendo con el puerto 3000 cambia por otro en el archivo app.js, específicamente en estas líneas:

      // Start server
      app.listen(3000, function() {
      console.log(“Node server running on http://localhost:3000“);
      });

      Estoy atento para poder ayudarte en lo que sea. Saludos!

  • JM Mta

    Muy buena información, te felicito..!!!, soy un novell en el desarrollo web y estoy tratando de hacer una app en nodejs, pero en mi caso estoy utilizando neo4j, la pregunta es…se puede hacer lo mismo con neo4j..???, por que la información que he conseguido cuando hacen la conexion es muy esqueta es decir ellos colocan el usuario y la clave visible en el codigo fuente, como podria hacerlo de manera mas segura…..

    • Hola, en este caso el tutorial solo cubre MongoDB, como para utilizar como base de datos, pero vos le podrías aplicar sin problemas la misma estructura para usar neo4j.

      En cuanto al manejo del usuario y contraseña, podrías crear un archivo de configuración que se encargue de gestionar eso, por ejemplo creas un archivo llamado database.js (y que ese archivo no se suba al repositorio, o sea tendrías que agregarlo al gitignore) y también creas un archivo llamado database-sample.js que tenga lo mismo que el archivo anterior pero sin el usuario, ip, y contraseña para que pueda ser subido al repositorio. De ese modo estarías asegurando esos datos importantes para que no se filtren, espero poder ayudarte en algo. Saludos,