Buenas prácticas en el diseño de APIs

Publicado por Oscar Sanz el

Arquitectura de SolucionesAPISwaggerOpenAPI

En este post vamos a analizar cómo describir una API mediante un contrato en formato Swagger, partiendo de la normativa OpenAPI.

Para  el diseño de APIs os propongo utilizar las siguientes herramientas y estándares:

Estructura de una interfaz basada en Swagger

Las secciones que tenemos que tener en cuenta para documentar una API en formato Swagger son:

  • Información básica
  • Operaciones
  • Parámetros
  • Códigos de respuesta
  • Validaciones
  • Buenas prácticas de diseño

Información básica

La información básica que define un swagger se compone de los siguientes apartados:

  • Versión del lenguaje
  • Información general de la interfaz
  • Tipo de Licencia
  • Nombre del Host
  • Protocolos de transporte válidos
  • Seguridad

Esta información se utiliza como documentación y no es crítica en la generación de un cliente para consumir las operaciones descritas en el contrato.

La siguiente imagen representa un ejemplo de cómo documentar esta sección:

Operaciones

Las operaciones de un contrato para una API representa como va a interactuar el cliente con las entidades (información) gestionada por la API.

Las operaciones en una API se describen mediante "verbos". Los operaciones que describe una API se pueden clasificar en los siguientes grupos:

  • Operaciones seguras: Obtener información de las entidades.
  • Operaciones de modificación: Necesitan un payload con la información a crear o modificar en el servidor.
  • Operaciones de información: Obtener información del backend.

La siguiente imagen representa los grupos descritos anteriormente:

Parámetros

Las operaciones que se describen en un contrato requieren de información variable para acceder a la información. Esta información puede ser:

  • Parámetros de navegación (Path Parameters)
  • Parámetros de filtrado (Query Parameters)
  • Payload de información (Payload)

Para describir esta información se recomienda documentar la siguiente información:

  • Tipo de Objeto (Ej. String)
  • Tamaño máximo
  • Obligatoriedad (Mandatory)
  • Expresión regular que define el formato (Ej. Formato de un correo electrónico)
  • Lista de valores válidos (Ej. Listado de Provincias)
  • Esquema del objeto
  • Formato del mensaje (Ej. application/json)

Las siguientes imágenes representan algunos ejemplos de cómo definir los diferentes tipos de parámetros:

Códigos de respuesta

Cuando hablamos de una API REST las respuestas deben estar basadas en un código HTTP que identifique de forma unívoca la operación.

Adicionalmente el equipo de desarrollo del backend debe tener en cuenta que las operaciones deben ser implementadas desde un punto de vista de inmutabilidad, es decir para una misma operación debe devolver el mismo código HTTP si se ejecuta con éxito.

La siguiente imagen representa los códigos HTTP que se recomienda implementar para una operación POST:

Un ejemplo claro se puede describir cuando se elimina un elemento de una entidad con la operación DELETE donde se puede dar los siguientes escenarios:

1.- El elemento existe y se borra con éxito.
2.- El elemento se eliminó en una operación anterior.
3.- El elemento nunca ha existido en el backend.

Si utilizamos la descripción de los códigos HTTP para cada escenario podríamos devolver un código HTTP diferente provocando que la implementación del cliente sea mucho más compleja de implementar y mantener.

La siguiente imagen representa las categorías que representan los códigos HTTP:

El listado de todos los códigos HTTP se puede consultar en el siguiente enlace.

Validaciones

Actualmente están apareciendo herramientas que nos permiten validar la calidad de nuestros contratos.

La herramienta que utilizo para garantizar que las APIs tienen toda la información requerida por un tercero es apisecurity.io:

En el siguiente enlace puedes encontrar el contrato en formato Swagger utilizado en este artículo.

Buenas prácticas de diseño

Adicionalmente, aunque nuestra API tenga una validación de 100 puntos, es recomendable tener en cuenta las siguientes buenas prácticas:

1 - Una entidad en una API no debe representar una tabla en nuestro modelo Entidad-Relación

2 - No proporcionar información sensible (Ej. Hashcode de una password)

3 - No utilizar "Primary Keys" o "Foreign Keys" como parámetros (Path parameters)

4 - Una API REST representa Entidades y no Acciones

5 - Las operaciones de una API REST no deben tener estado (deben ser idempotentes)

6 - Las operaciones que requieran una complejidad alta en el servidor se deben gestionar de forma Asíncrona.

7 - Utilizar cabeceras para validar el formato de la información mediante cabeceras (Ej. Content-Type)

Conclusión

En este artículo hemos repasado de forma muy práctica cómo documentar una API REST mediante un contrato en formato Swagger y herramientas que te pueden ayudar en la generación y validación.

Si te ha gustado, ¡síguenos en Twitter para estar al día de nuevas entregas!