Si no sabes qué es una API REST, recomiendo leer sobre esto aquí.
A modo de breve resumen, construir una API de forma REST significa que tienes que construir sus endpoints de URL agrupados por "recursos". Un recurso es algo que quieres gestionar, por ejemplo: un estudiante, un usuario, un auto, etc. Un recurso es algo similar a una tabla de base de datos, pero los llamamos "recursos" debido a algunas excepciones.
Aquí hay un ejemplo de endpoints RESTful API para gestionar Estudiantes:
Método | URL | Descripción |
---|---|---|
GET | /estudiante | Debería devolver todos los estudiantes |
GET | /estudiante/1 | Debería devolver un solo estudiante con el id=1 |
GET | /cohort/1/estudiantes | Debería devolver todos los estudiantes de la clase con el id=1 |
POST | /estudiante | Debería crear un nuevo estudiante |
PUT | /estudiante/1 | Debería actualizar la información del estudiante con el id=1 |
DELETE | /estudiante/1 | Debería eliminar al estudiante con el id=1 |
Echa un vistazo a las URL, ellas siguen un patrón. Después de un tiempo, los endpoints hablarán por sí mismos, tendrán sentido y podrás adivinar a lo que hacen o incluso adivinar algunos endpoints. Esa es la idea.
☝️ Puede leer más sobre las API REST en esta lección de BreatheCode.
Aquí hay un video de 8 minutos que explica REST: https://www.youtube.com/watch?v=7YcW25PHnAA
Expressjs es la librería que nos permite construir un servidor web API de una forma rápida, minimalista y flexible utilizando nodejs. El primer paso para utilizarla es realizando la instalación en tu proyecto, para esto en tu terminal debes ejecutar:
$ npm install express --save
Una vez finalizada la instalación crearemos un archivo server.js en donde agregaremos las siguientes líneas. El computador comenzará a escuchar las solicitudes HTTP:
1const express = require('express'); 2const app = express(); 3 4app.get('/', (req, res)=>{ 5 res.send("Hello World!") 6}) 7 8 9app.listen(4000, function(){ 10 console.log('API en ejecución en el puerto 4000'); 11})
Haz clic para probar este código en vivo.
1const express = require('express'); #aquí importamos la librería Expressjs en nuestro archivo. 2const app = express(); #aquí creamos una nueva instancia del servidor Express.js. 3 4app.get('/', (req, res)=>{ #aquí definimos el primer path de la API: GET / 5 res.send("Hello World!") #expressjs devolverá "Hello World, esto podría ser un string HTML o un string JSON. 6}) 7 8 9app.listen(4000, function(){ #finalmente iniciamos el servidor en el localhost. 10 console.log('API en ejecución en el puerto 4000'); 11})
En Expressjs podemos agregar nuevos endpoints utilizando la variable app
que es la instancia que definimos de expressjs y agregando el método http donde se encontrará disponible nuestro endpoint app.get('/', (req, res)=>{}
, como puedes ver tendremos una función de devolución de llamada que recibirá 2 parámetros req, res
. El detalle de estos parámetros es el siguiente:
req : Es un objeto que representa la solicitud HTTP y nos entrega información del request como el body, query params, HTTP headers.
res : Es un objeto que representa la respuesta HTTP que envía la aplicación Express cuando recibe una solicitud HTTP
En el siguiente link puedes acceder a la documentación de Express.js
Si deseas agregar otro endpoint a tu API que se ejecute cuando un cliente haga el GET/person
, tendrás que agregar otro bloque de código como este:
1app.get('/', (req, res)=>{ #aquí definimos el primer path de la API: GET / 2 res.send("Hello World!") #expressjs devolverá "Hello World, esto podría ser un string HTML o un string JSON. 3})
Si deseas que tu endpoint responda a POST, PUT o DELETE, puedes especificarlo de la siguiente manera:
1const express = require('express'); 2const app = express(); 3 4app.get('/', (req, res)=>{ #aquí definimos el primer path de la API: GET / 5 res.send("Se recibió un GET") 6}) 7 8app.post('/', (req, res)=>{ #aquí definimos el primer path de la API: POST / 9 res.send("Se recibió un POST") 10}) 11 12app.listen(4000, function(){ #finalmente iniciamos el servidor en el localhost. 13 console.log('API en ejecución en el puerto 4000'); 14})
La respuesta puede ser básicamente lo que quieras siempre que sea un string: HTML, JSON, CSS, imágenes, etc. Solo asegúrate de convertir en string lo que quieras responder.
En el siguiente ejemplo, estamos utilizando el método JSON.stringify para convertir un objeto llamado person1
en en un string JSON antes de devolverlo al cliente.
1const express = require('express'); 2app.get('/person', (req, res)=>{ 3 const person1 = { 4 "name": "Bob" 5 } 6 res.status(200).json(person1); 7})
El código de respuesta es 200 por defecto, y 500 si hay un error desconocido. Si deseas responder al cliente con un código diferente, deberás especificarlo así:
1const express = require('express'); 2app.get('/person', (req, res)=>{ 3 const contenido = { 4 "detalles": "Hubo un error en la solicitud" 5 } 6 res.status(400).json(contenido); # aquí cambiamos el código de estado a 400 (código muy común en caso de errores de solicitud) 7})
Pero ¿y si la solicitud viene con errores? Por ejemplo: si tenemos un endpoint para crear una persona y debemos especificar el first_name
y el last_name
, pero solo se encontró el first_name
en la solicitud, así es como lo validaríamos:
1const express = require('express'); 2 3app.use(express.json()) // Permite parsear el contenido en un tipo application/json 4app.use(express.urlencoded({ extended: true })) // Permite parsear el contenido en un tipo application/x-www-form-urlencoded 5 6 7app.post('/person', (req, res) => { 8 const { body } = req; 9 10 if (!body) { 11 return res.status(400).json({ message: "The request body is null" }); 12 } 13 14 if (!body.hasOwnProperty('first_name')) { 15 return res.status(400).json({ message: "The request first_name is null" }); 16 } 17 18 if (!body.hasOwnProperty('last_name')) { 19 return res.status(400).json({ message: "The request last_name is null" }); 20 } 21 22 return res.status(400).json(body); 23})
La librería express-validator
nos entrega una forma más cómoda para el manejo de las validaciones, pueden obtener más información de como usarla visitando su documentación https://express-validator
Un middleware es una función que tiene acceso al objeto de solicitud o request, al objeto de respuesta o response y a la siguiente función de middleware a ejecutarse en el ciclo de solictud/respuesta. Una vez que nuestro middleware termine su ejecución es importante ejecutar la función next()
o la solicitud quedara colgada.
A continuación un ejemplo de un middleware que imprimirá por consola la fecha y hora en la que ocurren las consultas a la API
1const express = require('express'); 2 3app.use(function (req, res, next) { 4 console.log('Time:', Date.now()); 5 next(); // aquí invoca al siguiente middleware 6}); 7
Hemos preparado este ejemplo de codificación en vivo que puede ejecutar tu mismo en Gitpod y utilizarlo como base para su proyecto.
Expressjs Rest Hello: https://github.com/4GeeksAcademy/expressjs-rest-hello