Spectral como herramienta para validación y verificación de APIs

Spectral es una herramienta open source de análisis que permite validar y verificar una API, el contrato, es decir, el documento en el que se establece como se deben estructurar las solicitudes y respuestas, se definen los endpoints, los modelos, información de contacto y seguridad... Con ello se logra asegurar que las APIs sean coherentes, estén bien documentadas y cumplan con los estándares definidos. Hoy en día esto es algo fundamental y se integra a la perfección con el enfoque API First.

Validar un contrato, a veces de miles de líneas, puede ser ardua tarea y una mala validación puede suponer pérdidas enormes para la empresa, tanto económicas como de reputación.

Gracias a Spectral, como veréis a continuación, se simplifica y se hace mucho más eficaz la validación y verificación de contratos, de cualquier tamaño y complejidad.

Hablemos de las reglas de Spectral y rulesets

La herramienta es un linter, esto es, analiza y hace cumplir una serie de reglas y estándares en documentos JSON o YAML. En general lo que analiza son objetos, json o yaml (partes o propiedades individuales).

Para entenderlo mejor, se puede poner como ejemplo de objeto el siguiente:

Se trata de un fragmento de un contrato y representa un endpoint y el verbo html POST con algunas propiedades.

Spectral valida contra un conjunto de reglas definidas en un fichero, indicando mediante mensajes las inconsistencias encontradas con diferente nivel de gravedad o importancia: ERROR, WARN, INFO o HINT.

Dicho fichero se conoce como ruleset. Es un fichero JSON, YAML o JavaScript/TypeScript en el que se definen el conjunto de reglas encargadas del análisis, junto con cierta configuración (es posible, por ejemplo, importar un conjunto de reglas externas).

Una regla toma una serie de parámetros y llama a 1 o varias funciones para validar ciertas partes o propiedades de un YAML o JSON. Estos parámetros son input (targetVal), options (opts) y context (path). Puedes darles el nombre que desees, pero siempre en ese orden. En este caso la sintáxis empleada es la más común y la que utilizan en la documentación oficial.

Para crear el ruleset podemos aprovechar un conjunto de reglas existentes, por ejemplo, Spectral trae 2 consigo:

Pero su verdadero potencial reside en que podemos crear los nuestros personalizados, adaptados al milímetro para cada contrato, haciendo que las API sean robustas y coherentes.

A continuación, se muestra un ejemplo de ruleset con sus propiedades:

Las propiedades de la imagen (extends, documentationUrl, formats...), a excepción de rules, son opcionales. Esto es, se pueden incluir en el ruleset o no.

En la propiedad rules es donde ocurre la magia, donde se señalan campos del contrato y se validan. Que mejor que verlo con un ejemplo, en el que se implementa una regla que localiza todos los endpoints definidos en un contrato (la propiedad given establece el/los jsonPath a los objetos del contrato) y aplica la función predefinida de Spectral, ‘pattern’, que permite validar si una cadena de texto coincide con un patrón específico definido por una expresión regular. La functionOption match especifica la expresión regular, como un parámetro adicional.

En esta regla el given recibe un único jsonPath, pero pueden ser varios. Por cada ocurrencia en el contrato de dicho path se aplica la regla y se muestra el message. En este caso es predefinido para cualquier ocurrencia, pero puede personalizarse y evaluarse en tiempo de ejecución como se ve en el segundo ejemplo.

Como se acaba de explicar, ‘pattern’ es una función predefinida por Spectral, pero no es la única. Se llaman core-functions y están listas para utilizarse, sin necesidad de implementación adicional (no obstante, existe la posibilidad de sobreescribirlas). Entre ellas se encuentran otras como ‘enumeration’,’ alphabetical’, ‘falsy’, ‘length’ o ‘defined’. En la web de spectral se puede ver en detalle cada una.

Esto está muy bien, pero puede ser que necesitemos algo más que estas reglas predefinidas, y, ¡por supuesto que hay algo más! Podemos extender las reglas a JavaScript e implementar nuestras propias funciones. Todo sin la mayor complicación del tipo: “el spectral yaml es difícil de configurar para importar las funciones”. Como se ha visto en la estructura del ruleset existe una propiedad functions, aquí especificamos el nombre de la función, que por defecto se encuentra en un directorio denominado “functions”, en la carpeta donde se encuentre el linter (fichero.spectral por defecto). Si se desea utilizar otro directorio para las funciones, se puede cambiar con una línea de código en el ruleset.

Digital Lover

A continuación, vamos a ver un ejemplo de una regla donde se aplica una función personalizada.

Esta función va a estar implementada en JavaScript y recibe como parámetro el campo urlPath, que es la ruta absoluta de un diccionario JSON que hemos creado en nuestro sistema. Sin embargo, es posible definir rutas relativas.

El given tiene diferentes Json paths, de forma que la función se aplica a cada bloque del contrato señalado por cada uno, de forma separada. Como message se devuelve uno personalizado, usando un valor placeholder evaluado en tiempo de ejecución.

Vamos a ver la potencia que tiene la función gracias a los tres parámetros básicos que recibe y que se han explicado antes.

En input la función recibe el valor señalado por el given en el contrato, la propiedad description. Lo que hace la función es leer el fichero de la ruta que se pasa en el argumento urlPath del functionOptions y comprueba si la description tiene alguna palabra que sea un tecnicismo almacenado en el fichero. Si es así devuelve un mensaje de error, que es capturado a través de {{error}} en la regla.

En este ejemplo no se ha usado el parámetro path o context, no obstante, se podría usar, por ejemplo, context.path para cargar la ruta del contrato, como un array al elemento apuntado, lo que permite, por ejemplo, obtener el endpoint correspondiente a la propiedad ‘description’ señalada y hacer una comparación, por ejemplo, si la descripción contiene algo parecido al endpoint, quie sale un mensaje de error. Esto evita recorrer el json o yaml en busca de dicha propiedad.

Spectral se integra con diferentes IDEs

Ya hemos visto el potencial de esta herramienta en cuanto a la validación de APIs, pero además puede integrarse con diferentes IDEs que mejoran la experiencia del usuario. Un contrato se puede validar contra Spectral por medio de un comando en terminal. Por ejemplo, al ejecutar el comando spectral lint base-openapi-OK.yaml --ruleset ../.spectral.yaml se aplica el linter (el ruleset) almacenado en el fichero “spectral” al contrato base-openapi-OK. El resultado de esto puede ser como el del ejemplo, en el que se muestra un mensaje de gravedad INFO indicando que el valor de campo ‘year’ del contrato no representa un año actual:

Pero también se puede integrar con Stoplight Studio o IntelliJ, e incluso con NodeJS para realizar tests del funcionamiento de las reglas sobre uno o varios contratos y diferentes rulesets. Además de esto, Visual Studio Code dispone de un plugin de Spectral, lo que facilita mucho la labor tanto de tests como de implementación de reglas y rulesets.

Stoplight facilita la visualización de inconsistencias, mostrándolas de manera atractiva y en tiempo real. Veamos un ejemplo:

Por otro lado, gracias a IntelliJ o Node JS es posible implementar un pool de pruebas de forma sencilla con cierta configuración del linter. Solo se necesita una función que carga el contrato, una función de configuración del linter que lanza las reglas al contrato indicado (es posible configurar la desactivación de ciertas reglas a la hora de validar), las funciones JavaScript, el contrato y el ruleset. Los tests se implementan, por ejemplo, en typescript y en ellos se especifica que regla se espera que salte al modificar un campo del contrato.

Para terminar

Contar con APIs coherentes y de calidad supone una gran ventaja en el mundo empresarial y tener una forma automatizada de hacerlo ahorra costes y muchos quebraderos de cabeza. Spectral no solo automatiza, si no que ofrece una forma muy visual y potente de verificar los contratos API. Al probar esta tecnología he ido descubriendo nuevas posibilidades cada día, opciones de configuración como la creación de alias para reutilizar en varias reglas los mismos json path, la posibilidad de incorporar rutas relativas, acceder al contrato completo desde la función JavaScript o la integración con IDES como IntelliJ o NodeJS para la elaboración de un pool de pruebas y validar reglas concretas con independencia o no del resto.

En conclusión, su enfoque automatizado y su capacidad para detectar errores tempranos hacen de Spectral una elección valiosa para cualquier organización cuyo objetivo es garantizar la fiabilidad y el rendimiento óptimo de sus APIs, convertidas, en la era digital que vivimos, en un método de negocio cada vez más popular y efectivo.

 

 

 

He leído y acepto la política de privacidad
Acepto recibir emails sobre actividades de recruiting NTT DATA