Creación de rutas para consultar y agregar los registros (4ª parte de creación de una API REST con Express y TypeScript)

Publicado el 02 noviembre 2022 por Daniel Rodríguez @analyticslane

En la publicación anterior se han explicado los pasos para configurar TypeORM en un proyecto TypeScript. Un ORM con el que se puede manejar de una forma sencilla los registros de una base de datos. Ahora, usando este conocimiento, se pueden crear unas rutas para consultar y agregar los registros de esta base de datos. Aunque primero es necesario hablar de los métodos o verbos HTTP.

Los métodos del protocolo HTTP

Al enviar una petición HTTP a un servidor es necesario incluir en esta el método o verbo. Un valor con el que se indica cuál es la operación que se desea realizar y, de esta manera, el servidor sepa que función ejecutar. El método más popular es GET, utilizado por los navegadores para obtener una página web. Aunque al trabajar con un API se puede recurrir a cualquiera de los siguientes GET, POST, PUT, PATCH, DELETE, HEAD, CONNECT, OPTIONS y TRACE.

En el caso de escribir un API para implementar operaciones tipo CRUD (create, read, update, and delete) los cuatro métodos HTTP más utilizados son:

  • GET: consultar los datos,
  • POST: agrega nuevos datos,
  • PUT: actualización de los datos,
  • DELETE: eliminación de los dados

Instalar Postman probar los diferentes métodos.

En las publicaciones anteriores todas las peticiones que se han realizado han sido GET, por eso la respuesta se ha podido leer con un navegador. Ahora, antes de continuar es recomendable instalar Postman, una herramienta con la que podrá construir y probar las llamadas a un API.

Para poder obtener Postman es necesario registrarse gratuitamente en su página web https://www.postman.com. Una vez creada la cuenta se podrá descargar la versión adecuada para nuestro sistema operativo.

Una vez instalada, se puede crear una nueva petición GET y probar el API el método que se ha creado anteriormente.

Obtener la respuesta del API con Postman

Indicar los métodos en Express

El uso de los diferentes métodos en Express es extremadamente intuitivo, simplemente se debe llamar al método que se desea ejecutar. Algo que se puede ver en el código que se ha usado en las publicaciones anteriores.

router.get('/', async (_req, res) => {
  res.send({
      message: `Server is running on port ${PORT}`,
  });
});

Hasta ahora para configurar la ruta siempre se ha empleado router.get(). Si se desea implementar el método POST se debería usar router.post(), para PUT router.get() y en el caso de DELETE router.delete(). Una forma bastante intuitiva de implementar los métodos.

Agregar un usuario a la base de datos

Para agregar un usuario a la base de datos es necesario implementar un método POST. Los datos que se deseen agregar se pueden indicar tanto a través de parámetros como en el cuerpo de la solicitud. En primer lugar, se puede ver cómo hacerlo a través de los parámetros de la llamada, para ello se puede escribir el siguiente código en la ruta.

router.post('/', (req: Request, res: Response) => {
  if (req.query.firstName & req.query.lastName) {
    const user = new User();
    user.firstName = String(req.query.firstName);
    user.lastName = String(req.query.lastName);

    datasource
      .getRepository(User)
      .save(user)
      .then((user) => res.send(user))
      .catch((error) => res.status(500).send({ message: error.message }));
  } else {
    res.status(400).send({
      message: `It is necessary to indicate the parameters 'firstName' and 'lastName' for the creation of a user`,
    });
  }
});

El uso de los diferentes métodos en Express es extremadamente intuitivo, simplemente se debe llamar al método que se desea ejecutar. Algo que se puede ver en el código que se ha usado en las publicaciones anteriores.

En este caso en primer lugar se comprueba si en la petición se pasan los dos parámetros necesarios, el nombre y los apellidos. Si no existe alguno se devolverá un mensaje de error indicando el problema en la petición. Nótese que en el caso de los mensajes de error se indica un código, en este caso 400 indicado que la solicitud no es válida. Es importante indicar este valor para que el usuario del API sepa lo que pasa en cada momento y reciba un estado 200, valor por defecto, indicando que todo ha ido bien.

Error que se obtiene al realizar una petición no valida

Insertar un usuario en la base de datos

Una vez comprobado que ha llegado tanto el nombre como los apellidos se puede agregar este a la base de datos. Para ello es necesario crear un nuevo objeto User y agregarle los valores. Ahora solamente se debe guardar el registro en la base de datos usando el método save:

datasource.getRepository(User).save(user)

Este método, al tener que guardar los valores en una base de datos externa, es asíncrono. En caso de que todo sea correcto, al finalizar la inserción, se ejecutará la función que se indique en then(). Por otro lado, siempre que se produce un error se ejecuta la función indicada en catch(). En el ejemplo se responde con el usuario cuando es correcto y con el mensaje de error cuando no lo es. Al igual que en el caso anterior es importante indicar que se ha producido un error asignado el estado 500 a la respuesta, lo que indica un error interno.

Agregar un usuario en la base de datos pasado los valores en los parámetros

Indicar el usuario en el cuerpo de la consulta

Cuando el objeto que se desea agregar es grande es mejor no pasar los datos en la URL, sino que el cuerpo del mensaje. Además de ser más seguro. Una de las opciones es parar los datos como un objeto JSON y para qué Express pueda procrearlo es necesario agregar un nuevo Middleware llamado json() que se encuentra en la propia librería. Así el archivo de middlewares/index.ts quedaría de la siguiente forma.

import cors from 'cors';
import { json } from 'express';
import helmet from 'helmet';
import morgan from 'morgan';

const middleWares = [cors(), helmet(), json(), morgan('tiny')];

export default middleWares;

Por otro lado, ahora también se tendrá que comprobar si en el body de la solicitud se encuentra un objeto usuario válido. Algo que se puede conseguir con el siguiente código.

router.post('/', (req: Request, res: Response) => {
  if (
    (req.query.firstName & req.query.lastName) ||
    (req.body.firstName & req.body.lastName)
  ) {
    const user = new User();

    if (req.query.firstName & req.query.lastName) {
      user.firstName = String(req.query.firstName);
      user.lastName = String(req.query.lastName);
    } else {
      user.firstName = String(req.body.firstName);
      user.lastName = String(req.body.lastName);
    }

    datasource
      .getRepository(User)
      .save(user)
      .then((user) => res.send(user))
      .catch((error) => res.status(500).send({ message: error.message }));
  } else {
    res.status(400).send({
      message: `It is necessary to indicate the parameters 'firstName' and 'lastName' for the creation of a user`,
    });
  }
});

En este punto se puede ir a Postman, borrar los parámetros y en la seleccionar la pestaña body, opción raw, en el desplegable JSON y agregar un JSON con un nuevo usuario.

Agregar un usuario con los valores en el body de la consulta

Consultar el listado de usuarios

Ahora que ya existen usuarios en la tabla de la base de datos, se puede consultar la lista creando un método GET que acceda a los datos. Para ello se puede usar el siguiente código en el que simplemente se leen los datos con el método find().

router.get('/', (req: Request, res: Response) => {
  datasource
    .getRepository(User)
    .find()
    .then((users) => res.send(users))
    .catch((error) => res.status(500).send({ message: error.message }));
});

Obteniendo como resultado al llamar al método los usuarios en un JSON.

Listado de los usuarios en la base de datos

Limitar el número de usuarios

En este ejemplo exportar todos los datos no es un problema, solamente hay tres usuarios. Pero en una base de datos real con miles o millones de registros obtener todos es un problema. Algo que se puede solucionar indicando los límites en la función find() de TypeORM.

Existen dos propiedades que son de interés en este momento: take y skip. La primera take permite indicar cuántos registros se desean obtener como máximo de la consulta. Un valor que es aconsejable limitar por defecto para evitar que el sistema tarde en responder. El segundo skip permite indicar los registros que se omiten de la consulta, comenzado el listado en el siguiente. La combinación de ambos permite paginar fácilmente las consultas para obtener respuestas pequeñas y rápidas.

Así el siguiente código le añaden dos parámetros opcionales con los que se pueden indicar el punto de inicio y el número máximo de usuarios. Si no se indica nada, la nueva consulta devolverá únicamente los 10 primeros usuarios.

router.get('/', (req: Request, res: Response) => {
  const skip = Number(req.query.from) || 0;
  const take = Number(req.query.take) || 10;

  datasource
    .getRepository(User)
    .find({ skip, take })
    .then((users) => res.send(users))
    .catch((error) => res.status(500).send({ message: error.message }));
});

Conclusiones

En esta entrada se ha visto cómo se pueden crear rutas para consultar y agregar los registros en Express. La semana que viene se verá como modificarlos y eliminarlos.

Imagen de Tayeb MEZAHDIA en Pixabay