Cómo hacer una API REST con Node.js

En artículos anteriores hemos visto cómo hacer la primera configuración de las herramientas que vamos a instalar así como a organizar nuestro proyecto utilizando el patrón Modelo-Vista-Controlador. Pues bien, hoy toca entrar en materia y vamos a comenzar a hacer una API REST con Node.js.

Un primer paso necesario para seguir estudiando Node.js y una buena base para que después podamos crear una aplicación SPA, o consultar la API desde un proyecto Symfony o para hacer que nuestra aplicación móvil pueda explotar esos datos oooo yo que sé…. las posibilidades son infinitas así que empecemos!

Cómo hacer una API REST con Node.js

A lo mejor a mas de uno esto de hacer una API REST con Node le suena a chino así que lo mejor que podemos hacer es ver primeramente qué es eso de una API REST.

¿Qué es una API REST?

Pues es lo que se conoce como una interfaz de comunicación entre clientes que utilicen el protocolo HTTP. Para que se entienda, es el canal por el cual tu móvil le dice a los servidores de Clash Royale que has abierto un cofre y te ha tocado el mago eléctrico o por ejemplo es el canal que utiliza Instragram para subir las fotos que haces con tu smartphone a sus servidores.

¿Se entiende el concepto?

Hoy en día podemos encontrar usos de APIs en casi toda cosa tecnológica que nos imaginemos pero el concepto de API no es nuevo ya que hace años existía otro tipo de APIs que parecía ser el rey del desarrollo. Hablo de SOAP y su intercambio de datos mediante XML. Hasta que debido a su facilidad llegaron las API REST y el intercambio mediante JSON.

Principalmente con una API REST vamos a echar mano de lo que se conoce como verbos HTTP. En concreto 4 y cada uno de estos verbos los utilizaremos para una acción u operación diferente con los datos que queremos manipular.

Así pues:

  • Cuando queramos subir una imagen nueva a Instragram utilizaremos el método POST del protocolo HTTP.
  • Cuando queramos saber cuántos seguidores tenemos en Twitter utilizaremos el método GET del protocolo HTTP.
  • Cuando queramos eliminar nuestro último estado de Facebook utilizaremos el método DELETE del protocolo HTTP.
  • Cuando queramos actualizar la foto de perfil de Snapchat utilizaremos el método PUT del protocolo HTTP.
  • Cuando queramos ver la lista de seguidores de VK utilizaremos el método GET del protocolo HTTP.

Hasta aquí esto es lo mínimo que podemos hacer con una API REST pero si quieres saber mas te recomiendo que le eches un vistazo a este artículo en el que se explica muy bien toda esta película, que nosotros nos vamos a poner a hacer ya una API REST con Node.js 😀

Cuatro verbos para dominarlos a todos

¿Os acordáis de la aplicación sobre álbumes musicales que empezamos a crear en los artículos anteriores? Si no te acuerdas o todavía no los has visto retrocede un poquito en el tiempo desde este enlace y desde este y cuando los hayas terminado vuelve aquí para seguir con la API REST con Node.js

Pero para el que si que se acuerde mediante el patrón MVC llegamos a organizar los ficheros de nuestro proyecto de una forma lógica y funcional ¿no?

También te acordarás de que hicimos un pequeño controlador para probar ¿no? De hecho llegamos a definir los métodos mínimos que tiene que tener nuestra API pero la gran mayoría de estos métodos lo único que hacia era recibir los datos de la request y devolverlos en la response. No había lógica de negocio alguna.

Pues ha llegado el momento de darle cuerpo a esos métodos 🙂

Método GET, consultar datos en una API REST con Node.js

Este es el primer verbo que vamos a ver de nuestra API REST con Node.js y es que tiene dos aplicaciones. Por un lado podemos utilizarlo para que nos devuelva un listado de elementos y por otro lado si le pasamos un identificador (lo mas normal debido a su unicidad) obtendremos los datos de un solo registro.

Aclaro que no es necesario pasar un id, podemos pasarle cualquier parámetro aunque en los métodos tipo getBy lo mas normal es pasarle el identificador.


var Album = require('../models/album');
function getAlbum(req, res){
var albumId = req.params.id;
Album.findById(albumId, function(err, album) {
if(err) {
res.status(500).send({message: 'Error 500 al devolver el album'});
}else{
if(!album){
res.status(404).send({message: 'No hay album'});
}else{
res.status(200).send(album);
}
}
});
}
function getAlbumes(req, res){
Album.find({}).sort('-_id').exec((err, albumes) => {
if(err){
res.status(500).send({message: 'Error 500 al devolver los albumes'});
}else{
if(!albumes){
res.status(404).send({message: 'No hay albumes'});
}else{
res.status(200).send({albumes: albumes})
}
}
});
}

view raw

album.js

hosted with ❤ by GitHub

Fijaos, aquí tenemos el ejemplo de estos dos métodos GET de la API y que nos devolverán ya sea un elemento o varios elementos. Pero hay varias cosas importantes que explicar:

  1. Hay que incluir el modelo, eso se hace en la primera línea del código anterior mediante un require.
  2. Mediante la sentencia req.params.id de la linea 4 estamos accediendo al valor que le pasamos a la ruta como parámetro.
  3. En la línea 6 encontramos el método findById() que es definido por el ORM de Mongoose y que nos provee de una capa de abstracción para explotar datos. Este método acepta el identificador que ha de buscar y una función de callback.
  4. Línea 20 encadenamos el método find() y el método de ordenación sort(). Si al método find() no le pasamos ningún argumento tan solo un objeto vacío por defecto nos sacará todos los registros de ese modelo de nuestra base de datos. Por otro lado, el método sort() espera un argumento por el cual ordenar el listado.

Estos dos métodos de nuestra API matchearán con las siguientes rutas (recuerda, has de tenerlas definidas)

Método POST, guardar datos en una API REST con Node.js

Bien, el siguiente método que vamos a construir es el que se encarga de guardar datos y va a ir por POST.


function saveAlbum(req, res){
var album = new Album();
var params = req.body;
album.title = params.title;
album.band = params.band;
album.genre = params.genre;
album.year = params.year;
album.save(function(err, albumStored){
if(err){
res.status(500).send({message:'Error al guardar el album'});
}else{
res.status(200).send({album: albumStored});
}
});
}

view raw

album.js

hosted with ❤ by GitHub

  • Si antes accedíamos a los argumentos pasados por GET en la ruta mediante la sentencia req.params.id, ahora para obtener los valores pasados por el método POST tenemos que hacer uso de la sentencia req.body (línea 3)
  • Seteamos los valores de la instancia del modelo con lo que nos ha traído la petición POST de la línea 5 a la línea 8.
  • Hacemos uso del método definido por Mongoose save() para guardar estos datos. Este método acepta una función de callback que recibirá el error en caso de producirse o el objeto ya almacenado.
  • Lo demás es hacer unas comprobaciones mínimas para asegurar la integridad de los datos y a correr 🙂

Método PUT, actualizar datos en una API REST con Node.js


function updateAlbum(req, res){
var params = req.body;
var albumId = req.params.id;
Album.findByIdAndUpdate(albumId, params, function(err, album){
if(err){
res.status(500).send({message: 'Error 500 al actualizar el album'});
}else{
res.status(200).send(album);
}
});
}

view raw

album.js

hosted with ❤ by GitHub

Este es el método de nuestra API que se va a encargar de actualizar datos.

  • Va a recibir los datos a actualizar mediante POST (línea 2)
  • Va a recibir el identificador del objeto a actualizar mediante GET, a través de la URL (línea 3)
  • El método findByIdAndUpdate() nos es provisto por el ORM Mongoose y acepta el identificador del objeto a actualizar, los datos a actualizar y una función de callback con el error (si es que hay alguno) y el objeto ya actualizado.

He de aclarar que gracias al middleware body-parser y que ya aprendimos a instalar en los artículos anteriores, todo lo que nos llegue por POST es transformado en objeto automáticamente, así podemos manipular los parámetros de una forma bien sencilla.

La URL definida para este método ha de ser de la siguiente forma:

Método DELETE, borrar datos en una API REST con Node.js

El último método del CRUD de nuestra API REST con Node.js es el método que se va a encargar de borrar y que funciona a través del método DELETE del protocolo HTTP.


function deleteAlbum(req, res){
var albumId = req.params.id;
Album.findById(albumId, function(err, album){
if(err){
res.status(500).send({message: 'Error 500 al devolver el album'});
}else{
if(album){
album.remove(err => {
if(err){
res.status(500).send({message: 'Error 500 al borrar el album'});
}else{
res.status(200).send({message:'El album se ha borrado'});
}
});
}else{
res.status(400).send({message:'No hay album'});
}
}
});
}

view raw

album.js

hosted with ❤ by GitHub

  • Este método aceptará un único argumento que se pasa por la URL (el identificador del objeto) y que recogemos mediante la sentencia req.params.id (línea 2)
  • Gracias al ORM Mongoose podemos hacer uso del método findById() para encontrar el objeto que coincida con el identificador pasado por parámetro (línea 4).
  • Gracias al método remove() podemos eliminar el objeto solicitado (línea 9)

Con esto ya tenemos los 5 métodos necesarios para que el CRUD de nuestra API REST con Node.js funcione pero claro, necesitamos un modelo de datos para que transforme los datos que recibimos en objetos que podamos manejar mas facilmente.

Ademas que realmente el modelo es necesario para que corran los códigos anteriores…. 😛


'use strict'
var mongoose = require('mongoose');
var AlbumSchema = new mongoose.Schema({
title: String,
band: String,
genre: String,
year: String,
});
module.exports = mongoose.model('Album', AlbumSchema);

view raw

album.js

hosted with ❤ by GitHub

Ea ahí tenéis el modelo de datos. Ese fichero ha de situarse en el directorio de models según la definición del patrón Modelo-Vista-Controlador y que aprendimos en el artículo anterior.

Vale Gorka, ya hemos aprendido a construir una API REST con Node.js perfecto, pero ahora… ¿cómo la probamos?

Pueeees para probar la API vamos a hacer uso de una extensión muy buena que se llama Postman y que podemos descargar desde aquí si utilizas Chrome.

He grabado un vídeo para que veáis cómo se usa.