Creando un API REST con Swagger Node (parte 2)

Ampliando el API haciendo uso de buenas prácticas

Diego Pérez Molinero
3 min readNov 11, 2017

En esta parte del artículo, vamos a ir ampliando el API con nuevas funcionalidades, intentando hacer uso de una serie de buenas prácticas que es bueno tener en cuenta a la hora de diseñar nuestro API.

Definición de los recursos con sustantivos y no como verbos

En nuestra api, hemos definido dos recursos: gamesystems y videogames, usando sustantivos, y para operar con los recursos hemos usado los métodos (GET, POST, PUT y DELETE) que tienen un significado concreto.

Si hubieramos definido nuestra API usando por ejemplo

/videogames/get o bien videogames/save o algo similar, no estaríamos aplicando correctamente los princicipios restful, donde se pone especial interés en los recursos.

Otro ejemplo, más parecido a lo que se conoce como RPC (Remote Procedure Call) sería algo similar a:

/getVideoGame o /saveVideoGame

Por lo tanto, nos centraremos en los recursos que exponemos en el API y usaremos los métodos de http para operar con ellos.

Definiremos los recursos usando nombres en plural

Es mejor usar plural en los nombres de los recursos, y evita encontrarse con plurales irregulares como mouse/mice o tooth/teeth. Facilita bastante el mantenimiento y la comprensión del API, sobre todo si vamos a exponerla para que sea consumida por terceros.

Devolución del recurso en los métodos POST, PUT y PATCH

Para evitar tener que volver a pedir el recurso una vez modificado o creado (con POST), es muy útil devolver el recurso en lugar de devolver un simple mensaje.

Para la creación de un nuevo objeto, devolvemos además el código http 201, en lugar de 200.

Filtrado de los datos

En nuestro API, para los métodos de obtención de datos, vamos a añadir una serie de parámetros para poder filtrar la información devuelta. Usaremos para cada campo un solo parámetro de filtro.

Para /gamesystems, queremos poder filtrar por nombre, así que añadiremos el filtro /gamesystems?name=<<nombre>>. Para hacerlo, añadimos una zona de parameters e indicamos el nombre, el método de entrada (que será query por venir en la query string, el tipo y si es requerido o no.

Para /videogames, podemos filtrar por name, developer, gamesystem, genre y y year.

Ordenación de los datos

Podemos especificar una ordenación en los datos devueltos, indicando por ejemplo un parámetro sort.

/gamesystems?sort=name

O bien para los videogames, si queremos ordenarlos por año de forma descendente y name, indicarlo así:

/videogames?sort=-year,name

Añadimos el parámetro de ordenacion a nuestro api, para los gamesystems:

Y para los videogames:

Limitación de los campos devueltos por nuestro API

Muchas veces, no queremos que se devuelvan todos los campos en una búsqueda, ya que no los necesitamos o bien queremos ahorrar ancho de banda (por ejemplo nuestro API será consumida por aplicaciones móviles, donde el lag de la red suele ser elevado).

En este caso, podemos aplicar un filtro especial, por ejemplo, con nombre fields.

/videogames?fields=name,year

- name: fields
in: query
type: string
required: false

De momento, lo aplicamos sólo al recurso videogames, ya que gamesystems sólo tiene dos campos.

Añadiendo a nuestro api contenido binario (imágenes)

Vamos ahora a añadir a nuestros recursos un campo más, para añadir una imagen identificativa de nuestro recurso. En el gaso de los gamesystem, podríamos añadir una imagen del dispositivo y para los videojuegos, una imagen de la portada.

Para añadir un tipo de dato en formato byte codificado a base 64, hay que poner el tipo a string, y el formato a byte:

image:
type: string
format: byte

Añadimos este nuevo campo en las definiciones de GameSystem, GetGameSystemResponse, y también en Videogame y GetVideoGameResponse

Sólo mostramos como hacerlo en GameSystem, en el resto de definiciones es simplemente añadirlo de la misma forma que hemos hecho.

Mensajes de error

En los mensajes de error, devolvemos aparte del mensaje de error, un código y una descripción.

Modificamos por tanto en la parte de definiciones el mensaje de error:

Hasta aquí ya tenemos una API más o menos completa, que podríamos ampliar introduciendo HATEOAS, versionado, cacheo, paginación, etc,..pero vamos a dejarlo para más adelante.

En la próxima parte del artículo veremos como implementamos todo en NodeJS.

Aquí podemos ver el código fuente de la segunda versión del API

En la siguiente parte del tutorial, veremos como empezar a implementar nuestra API:

Tercera parte

--

--

Diego Pérez Molinero

Software Architect & defender of clean architecture and domain driven design. Supporter of infrastructure & devops as code into the projects.