paint-brush
Diseño de API RESTful con Node.jspor@adnanrahic
236,909 lecturas
236,909 lecturas

Diseño de API RESTful con Node.js

por Adnan Rahić15m2020/03/08
Read on Terminal Reader
Read this story w/o Javascript
tldt arrow
ES

Demasiado Largo; Para Leer

Este tutorial lo guiará a través de los conceptos básicos del diseño de API con Node.js y Express. Le enseñará cómo configurar la columna vertebral de una API REST y cómo estructurar su código de manera lógica. La demostración completa está en GitHub si desea verla en su totalidad, está vinculada al final del artículo. Me encantaría que me siguieras y codificaras a medida que avanza el tutorial. Usaremos Express para esta aplicación, ya que es el estándar de facto para las aplicaciones Node en la actualidad. Usaremos MongoDB, una base de datos NOSQL, ya que no necesitamos una base de datos relacional.

People Mentioned

Mention Thumbnail

Companies Mentioned

Mention Thumbnail
Mention Thumbnail

Coin Mentioned

Mention Thumbnail
featured image - Diseño de API RESTful con Node.js
Adnan Rahić HackerNoon profile picture
Zeet patrocina esta entrada de blog para el próximo mes. Lo probé el otro día. Es como sin servidor pero para ejecutar back-ends completos. Puede alojar y escalar aplicaciones de forma automática. Con buena pinta.

Es una bestia notable de una herramienta, Node.js. Si es un principiante, aspirante a codificador o estudiante de TI, puede ser difícil entenderlo, pero cuando finalmente se acostumbra, es revelador. Este tutorial lo guiará a través de los conceptos básicos del diseño de API, enseñándole cómo configurar la columna vertebral de una API REST y cómo estructurar su código de manera lógica.

Me encantaría que me siguieras y codificaras a medida que avanza el tutorial. Cada fragmento de código irá seguido de una explicación, la mejor manera de entenderlo correctamente será codificarlo usted mismo en el camino.

Antes de comenzar, hay algunas cosas que debe saber sobre Node.js y algunos estándares de EcmaScript que usaré en el tutorial. No usaré ES6, ya que creo que no es tan amigable para principiantes como el JavaScript tradicional . Sin embargo, espero que ya conozca los conceptos básicos de Node.js, incluido cómo configurar un servidor Node básico que devolverá información según la ruta a la que accede el usuario. De lo contrario, tome un desvío y verifique esto antes de continuar.

"¡Hola Mundo!" aplicación con Node.js y Express
¿Usas nodo…? Vas a. medio.com

En segundo lugar, usaré la implementación básica de CommonJS. No se preocupe, esto se explicará a continuación. Siéntase libre de comprobarlo aquí , y aquí para más referencias. Sin embargo, no olvides volver a este tutorial. :)
Por último, la demostración completa está en GitHub si desea verla en su totalidad. Está vinculado al final del artículo.

¿Listo para algo de código?

No, es broma. Necesitamos configurar e instalar las dependencias requeridas y los módulos de nodo para que la aplicación funcione correctamente. Como crearemos una API, es obvio que se necesita una base de datos. Usaremos MongoDB , una base de datos NOSQL . Es la elección óptima para nuestras necesidades ya que no necesitamos una base de datos relacional. En lugar de instalarlo y ejecutarlo localmente, solo conectaremos una base de datos de espacio aislado en mLab , por simplicidad.

Pero tenga en cuenta que mLab es como un juguete. Sugiero usar MongoDB Atlas para alojar su base de datos en entornos de producción. Es el servicio oficial alojado en la nube de MongoDB.

Continúe, cree una cuenta y cree una nueva implementación de MongoDB.

En la página de inicio de su cuenta, cree una nueva implementación de MongoDB

Seleccione la base de datos sandbox gratuita y asígnele un nombre de su elección.

(Seleccione nodo único y sandbox)

Buen trabajo, solo una cosa más por hacer y su base de datos estará lista para la acción. Haga clic en su base de datos recién creada y siga las instrucciones escritas en texto amarillo. Presione la pestaña de usuarios y agregue un nuevo usuario.

(Agregue un nuevo usuario a su base de datos)

Eso es todo. La base de datos ya está lista para ser utilizada. Se conectará a él utilizando el URI de MongoDB indicado debajo del nombre de la base de datos.

Terminando eso, está listo para comenzar a configurar la aplicación en sí. Inicialice npm e instale los siguientes módulos:

 npm init npm install express --save npm install mongoose --save npm install body-parser --save


Usaremos Express para esta aplicación, ya que es el estándar de facto para la gran mayoría de las aplicaciones Node en la actualidad. Mongoose es un ORM — Mapeador relacional de objetos . El ORM oficial utilizado para MongoDB para ser precisos. Para desglosarlo, usamos un ORM para simplificar la transferencia de datos entre nuestra aplicación y la base de datos. Mapea los datos que tenemos en nuestra aplicación para mantener un conjunto de reglas estrictas establecidas por la base de datos. El módulo analizador de cuerpo es solo un middleware que usamos para analizar nuestros datos enviados a través de solicitudes HTTP.

Finalmente puedes escribir algo de código.

Saltemos de cabeza primero, ¿de acuerdo? Para comenzar, cree un archivo de aplicación y codifique una configuración básica. Escribe esto en tu app.js.

 // app.js var express = require ( 'express' ); var app = express(); module .exports = app;

Este archivo se usará para configurar la aplicación, y solo eso. Toda la lógica se colocará en su directorio respectivo con respecto a la característica específica que implementará. Usamos

 module.exports
para hacer que este objeto de aplicación sea visible para el resto del programa cuando lo solicitemos usando
 require()
.

Ahora tenemos que decirle a la aplicación dónde escuchar. Continúe y cree otro archivo, llamado server.js, y anótelo.

 // server.js var app = require ( './app' ); var port = process.env.PORT || 3000 ; var server = app.listen(port, function ( ) { console .log( 'Express server listening on port ' + port); });

Aquí puede requerir la aplicación y ponerla en una variable. Esta aplicación es el objeto de aplicación real que creó en app.js. Continúe eligiendo un puerto para que se ejecute la aplicación y finalmente active el servidor con app.listen. Continúe y abra una ventana de terminal y pruebe si esto funciona. Cambie al directorio donde creó estos archivos y ejecute node server.js. Debería ver que el servidor Express que escucha en el puerto 3000 se registra en la línea de comandos.

Tienes el servidor funcionando, ¡hurra!

Dos abajo, tres para ir. Con el servidor en funcionamiento, ahora necesita conectar la base de datos. Vuelva a su editor de texto y cree un nuevo archivo, asígnele un nombre muy innovador db.js , ya que se utilizará para almacenar la conexión de su base de datos. Debe tener un aspecto como este:

 // db.js var mongoose = require ( 'mongoose' ); mongoose.connect( 'mongodb://yourDatabaseURI' );

Cambia yourDatabaseURI por la URI mencionada anteriormente. Vuelva a su cuenta de mLab y copie el URI de MongoDB. Pégalo en tu código, entre las dos comillas. Cambie <dbuser> y <dbpassword> por las credenciales que ingresó para el usuario que creó. Una vez hecho esto, ahora debe decirle a la aplicación que tiene una conexión disponible. Simplemente agregue un

 require()
en app.js , así:

 // app.js var express = require ( 'express' ); var app = express(); var db = require ( './db' ); //ADD THIS LINE module .exports = app;

Al especificarlo de esta manera, le decimos que debe capturar un archivo en el mismo directorio donde se encuentra app.js e incluirlo. Eso es todo. Ahora nuestra aplicación sabe que tiene una base de datos lista y esperando a que se acceda a ella.

Su programa ahora debería tener tres archivos. Un app.js para configurar la aplicación, un db.js para especificar la conexión a la base de datos y un server.js para activar el servidor de nodos en un puerto específico de su elección.

Ahora está listo para comenzar a escribir la lógica comercial de su programa.

Ponerse manos a la obra.

Comience creando una nueva carpeta llamada usuario. Esta carpeta contendrá todos los archivos relacionados de alguna manera con nuestra comunicación con la base de datos con respecto a los usuarios. Comenzará creando un modelo de usuario. Este modelo servirá como modelo que muestra cómo se verán todos los usuarios en su base de datos. Cree un archivo llamado User.js y escriba este fragmento de código:

 // User.js var mongoose = require ( 'mongoose' ); var UserSchema = new mongoose.Schema({ name : String , email : String , password : String }); mongoose.model( 'User' , UserSchema); module .exports = mongoose.model( 'User' );

Está creando un esquema que le dará a cada usuario de la base de datos un aspecto específico. Un usuario tendrá un nombre, un correo electrónico y una contraseña. especificando

 mongoose.model('User', UserSchema)
está vinculando el diseño del esquema al modelo que se nombra
 'User'
. Esto es lo que usará para acceder a los datos en la base de datos, y es exactamente por eso que lo está exportando para usarlo en otras partes de su programa.

Ahora viene la parte divertida, crear rutas para su aplicación y vincularlas a las acciones respectivas.

Cree otro archivo y asígnele el nombre UserController.js . Lo nombrará con un controlador en su nombre, no solo por simplicidad, sino también porque contendrá las acciones que controlan el flujo de datos hacia y desde su base de datos.

 // UserController.js var express = require ( 'express' ); var router = express.Router(); var bodyParser = require ( 'body-parser' ); router.use(bodyParser.urlencoded({ extended : true })); router.use(bodyParser.json()); var User = require ( './User' ); module .exports = router;

Arriba está el diseño básico del controlador de usuario. Utilizará el enrutador express para crear un subconjunto de rutas que pueden ser modulares e independientes de toda la aplicación. Si alguna vez necesita reestructurar su programa, puede hacerlo fácilmente porque este enfoque le brinda la capacidad de desconectarlo de un lugar y conectarlo en otro. El módulo body-parser se usa como un middleware para manejar datos de una manera más elegante. Esto será útil cuando envíe datos a través de solicitudes HTTP utilizando formularios.

La parte divertida solo viene con

 require('./User')
. Ahora ve por qué necesitaba exportar el modelo de User.js. Comenzará a usarlo de verdad en UserController.js. Cada vez que crea un modelo como lo hizo anteriormente, automáticamente recibe todos los métodos necesarios para interactuar con una base de datos, incluidas las acciones de creación, lectura, actualización y eliminación. Finalmente, en la parte inferior del archivo, exporta el enrutador, ya que será necesario en app.js.

¡Estoy divagando!

Hagamos una introducción rápida a REST para comprender mejor las 4 acciones que tenemos a nuestra disposición para interactuar con una base de datos. Se llaman CRUD. Representación de C rear , Leer , Actualizar y Eliminar . Usando solicitudes HTTP, podemos usar la acción respectiva para activar cada una de estas cuatro operaciones CRUD.

  • POST se utiliza para enviar datos a un servidor — Crear
  • GET se utiliza para obtener datos de un servidor: lectura
  • PUT se utiliza para enviar y actualizar datos — Actualizar
  • ELIMINAR se utiliza para eliminar datos — Eliminar

La mejor manera de entender esto es saltar directamente.

De vuelta a los negocios.

 // UserController.js var express = require ( 'express' ); var router = express.Router(); var bodyParser = require ( 'body-parser' ); router.use(bodyParser.urlencoded({ extended : true })); router.use(bodyParser.json()); var User = require ( './User' ); // ADD THIS PART // CREATES A NEW USER router.post( '/' , function ( req, res ) { User.create({ name : req.body.name, email : req.body.email, password : req.body.password }, function ( err, user ) { if (err) return res.status( 500 ).send( "There was a problem adding the information to the database." ); res.status( 200 ).send(user); }); }); // RETURNS ALL THE USERS IN THE DATABASE router.get( '/' , function ( req, res ) { User.find({}, function ( err, users ) { if (err) return res.status( 500 ).send( "There was a problem finding the users." ); res.status( 200 ).send(users); }); }); module .exports = router;


Al observar el primer método, verá que el objeto del enrutador tiene un

 .post
método que toma dos parámetros. La primera es la ruta que se vinculará a una función. Esta función es el segundo parámetro. Toma otros dos parámetros que representan la solicitud al servidor y la respuesta del servidor. Dentro de la función, utilizará el modelo de usuario que solicitó anteriormente. El modelo de usuario tiene un método de creación que también toma dos parámetros. Siendo el primero un objeto y el segundo una función. El objeto contiene los valores que se insertarán en la base de datos. Verá, están estructurados como el esquema que creó anteriormente. Una vez creada, se llama a la función de devolución de llamada con otros dos parámetros, un valor de error y un valor de éxito . Comprobarás si hubo algún error durante la creación del nuevo usuario, y responderás en consecuencia, o si todo estuvo bien, responderás con los datos del nuevo usuario creado.

El segundo método es un poco más simple. El objeto enrutador también tiene un

 .get
método que también toma dos parámetros. Dentro de la función que ahora llamas
 find()
método en el modelo de usuario que también toma dos parámetros. Find es un método que devuelve valores de la base de datos. Su primer parámetro, un objeto, define los requisitos que deben cumplirse para devolver valores. Como en este ejemplo el objeto está vacío, se devolverán todos los usuarios de la base de datos.

Ahora, debe informar a la aplicación que tiene un controlador de usuario. Agregue esto a su app.js.

 // app.js var express = require ( 'express' ); var app = express(); var db = require ( './db' ); // ADD THESE TWO LINES var UserController = require ( './user/UserController' ); app.use( '/users' , UserController); module .exports = app;

Entonces, ¿qué magia está pasando aquí? Realmente no haremos nada. Estás requiriendo el controlador de usuario y con

 app.use
decirle a la aplicación que lo vincule a la ruta
 /users
. Ahora el
 /
la ruta dentro de su controlador de usuario se asignará a
 /users
. Esto es genial, ¿verdad?

¿Incluso prueba, hermano?

Uf, eso fue un puñado. Tomemos un descanso y probemos nuestra aplicación. Para probar las API, siempre uso Postman . Es una herramienta increíble para probar URL con las 4 acciones HTTP. También agrega la posibilidad de enviar datos en el cuerpo de las solicitudes HTTP. Exactamente lo que necesita para probar su aplicación. Descargue, instale y ejecute Postman y sígalo.

Postman es una herramienta bastante básica, ingresa la URL a la que desea enviar una solicitud HTTP, elige un método y, si es necesario, ingresa parámetros. Empecemos por enviar una solicitud POST a

 http://localhost:3000/users
. Esto significa que deberá ingresar un conjunto de parámetros en el cuerpo de la solicitud.

Cambie a la pestaña del cuerpo e ingrese la clave: pares de valores que coincidan con el modelo de usuario que creó anteriormente. Necesitas un nombre, un correo electrónico y una contraseña. Presiona enviar. ¡Voila! Una respuesta. Si todo salió bien, la respuesta contendrá datos que coincidan con el usuario creado recientemente.

Ahora, continúe y cambie el método HTTP a GET, y presione enviar una vez más. Verá que todos los usuarios creados se devuelven desde la base de datos. Continúe y juegue un poco con esto, agregue algunos usuarios más y observe cómo se comporta la solicitud GET.

Volver al código.

Hasta ahora, instaló un servidor, configuró su aplicación, la conectó a una base de datos y creó dos API para comunicarse con la base de datos. Quedan tres API más por implementar. Recuperar un solo usuario de la base de datos, actualizar un usuario y, finalmente, eliminar un usuario. Todos estos tienen una cosa en común. Todos tendrán un parámetro de consulta, a menudo llamado parámetro de ruta. No te asustes. Es solo un valor que se pasará a lo largo de la solicitud. Saltemos.

 // UserController.js //... // GETS A SINGLE USER FROM THE DATABASE router.get( '/:id' , function ( req, res ) { User.findById(req.params.id, function ( err, user ) { if (err) return res.status( 500 ).send( "There was a problem finding the user." ); if (!user) return res.status( 404 ).send( "No user found." ); res.status( 200 ).send(user); }); }); //...

Ahora ha agregado otra solicitud GET, pero mire la ruta, el primer parámetro del método router.get. Ahora tiene un valor que consiste en dos puntos seguidos de algún texto. Esta notación significa que es un marcador de posición para un parámetro de consulta, un valor simple, que se enviará junto con la solicitud. Se podrá acceder al valor pasado a '/:id' a través del objeto req.params. Donde el nombre del parámetro de consulta se asignará a una propiedad con el mismo nombre en el objeto req.params.

Continuando, Mongoose tiene un método increíble llamado .findById que solo querrá la ID por la cual devolverá un usuario. El ID es el primer parámetro y la función de devolución de llamada es el segundo. ¿Puedes ver un patrón emergente? Todos los métodos de Mongoose quieren un valor como primer parámetro y una función de devolución de llamada como último. Esta devolución de llamada se llamará después de que la base de datos haya devuelto el valor consultado. El mismo patrón también se puede ver con la solicitud DELETE.

 // UserController.js //... // DELETES A USER FROM THE DATABASE router.delete( '/:id' , function ( req, res ) { User.findByIdAndRemove(req.params.id, function ( err, user ) { if (err) return res.status( 500 ).send( "There was a problem deleting the user." ); res.status( 200 ).send( "User " + user.name + " was deleted." ); }); }); //...

los

 router.delete
El método se ve exactamente igual que el
 router.get
arriba. Incluso el método Mongoose tiene el mismo aspecto, con la excepción de su nombre. Eliminará a un usuario de la base de datos al proporcionarle al método la ID de un usuario que desea eliminar. los
 .findByIdAndRemove
El método encontrará un usuario como
 findById
pero también lo eliminará de la base de datos.

El paso final en su aplicación será implementar una forma de actualizar un usuario existente en la base de datos. Esto se hace con una solicitud PUT.

 // UserController.js //... // UPDATES A SINGLE USER IN THE DATABASE router.put( '/:id' , function ( req, res ) { User.findByIdAndUpdate(req.params.id, req.body, { new : true }, function ( err, user ) { if (err) return res.status( 500 ).send( "There was a problem updating the user." ); res.status( 200 ).send(user); }); }); //...

La solicitud router.put es muy similar a las dos solicitudes que escribió anteriormente. También toma un parámetro de consulta, un ID. Lo que lo hace diferente es que también toma parámetros del cuerpo, al igual que la solicitud POST que escribiste primero. Los únicos métodos HTTP que tienen cuerpo son POST y PUT. Recuérdalo.

¿Te importa adivinar qué hace .findByIdAndUpdate? Estás bien. Este método es un poco diferente de los que escribiste anteriormente. Toma tres parámetros principales, una ID, un objeto correspondiente al usuario cuyos valores se actualizarán y, por supuesto, una función de devolución de llamada. Pasará el cuerpo de la solicitud como el segundo parámetro, el objeto, ya que el middleware que requerimos y usamos en la parte superior de UserController.js ya lo analizará correctamente. Una buena práctica al actualizar algunos valores es solicitar que se le envíe el valor actualizado. Esto es importante ya que desea tener acceso al valor recién actualizado. Por lo tanto, agrega otro cuarto parámetro {nuevo: verdadero} que representa la opción de qué versión del valor, en su caso, el usuario, desea devolver. El anterior a la actualización, o el posterior. Devolver este valor le mostrará el usuario que actualizó.

¿Listo para más pruebas?

La programación es a menudo un equilibrio entre el caos y la serenidad. El caos de resolver problemas aparentemente ilógicos, versus la serenidad cuando finalmente los resuelves. Probar es cómo se gana serenidad. Me he encontrado con un dicho profundamente arraigado en la mentalidad de todos los programadores que he conocido.

Escribir código que funciona en el primer intento, la primera compilación o la primera ejecución, se denomina premio mayor de programación.
— Todos los programadores de la historia

Cuando realmente sucede, si es que sucede alguna vez, sientes como si el sol hubiera elegido brillar especialmente sobre ti. No te acostumbres a esto. Construye un entendimiento de que esto nunca sucede. Debe hacer clic en cosas, presionar botones y sumergirse en las herramientas de desarrollo para poder calmar el caos y lograr la serenidad.

¿Listo? Presionemos algunos botones.

Inicie un símbolo del sistema una vez más y active su servidor con node server.js. Abra Postman y siga adelante y pruebe los nuevos métodos que acaba de crear. Una solicitud GET ordinaria para un solo usuario se vería algo así:

Agregar la ID del usuario en la URL como un parámetro de consulta solo devolverá al usuario con esa ID en particular.

Pasando a una solicitud PUT, cambie el método a PUT, agregue valores al cuerpo (asegúrese de que las propiedades coincidan con las propiedades del esquema de usuario que creó anteriormente) y presione enviar.

Ha cambiado el nombre del "administrador" a "imNotTheAdminAnymore".

Si entiende esto, el método DELETE será pan comido. Cambie el método a ELIMINAR y presione enviar una vez más. Ahora eliminará el usuario con la ID dada de la base de datos.


Entiendo que entender todo esto tan pronto es difícil. Es por eso que envié todo el código a GitHub. Si te quedas atascado en algún lugar, no dudes en echar un vistazo a todo el proyecto en su totalidad aquí . O si quieres leer mis últimos artículos, dirígete aquí.

Últimas historias escritas por Adnan Rahić - Medium
Lee las últimas historias escritas por Adnan Rahić en Medium. Ingeniero de software @bookvar_co. Educador de codificación @ACADEMY387... medium.com

¿Así que pensaste que era eso?

Solo has raspado la punta de un enorme iceberg. Pero, es suficiente por ahora. Sea curioso, haga preguntas y siga presionando botones. Te he dado los conceptos básicos de muchas habilidades básicas que necesitarás saber en tu viaje al estrellato.

No dejes que Node te asuste. Es simplemente JavaScript. Véalo de la misma manera que lo haría con el código que escribe en un navegador. Para desglosarlo, es solo un grupo de detectores y controladores de eventos. Por ejemplo:

 router.get( '/:id' , function ( req, res ) { User.findById(req.params.id, function ( err, user ) { if (err) return res.status( 500 ).send( "There was a problem finding the user." ); if (!user) return res.status( 404 ).send( "No user found." ); res.status( 200 ).send(user); }); });

El servidor está escuchando una solicitud HTTP para llegar a la ruta

 '/:id'
con un método GET. Cuando se produce una solicitud de este tipo, se llamará a la función de devolución de llamada. Todo lo que esté dentro de esta función será evaluado y ejecutado. ¿No es familiar?

 button.addEventListener( 'click' , function ( e ) { console .log( "Well it's very familiar for me." ); });

Espero que hayan disfrutado leyendo esto tanto como yo disfruté escribiéndolo. Ten curiosidad, seguro que me ha ayudado mucho.

¿Crees que este tutorial será de ayuda para alguien? No dudes en compartir. Si te gustó, haz clic en el aplauso de abajo para que otras personas lo vean aquí en Medium.

Gracias a mi papá, por ser mi inspiración y mantenerme siempre curiosa.