La evolución del API

Del API Rest al Open API

Alan Badillo Salas
big-data-for-humans
5 min readAug 18, 2019

--

La idea de formar un API (Application Programming Interface o Interfaz de la Programación de la Aplicación) es brindar un recurso ya sea de datos o de cómputo mediante una estructura invariante que pueda ser mantenida en el transfondo sin perder la operabilidad.

La forma más común de programar un API se ha convertido en la declaración de un API Rest, que en esencia es un esquema basado en el protocolo HTTP mediante el cuál se le puede solicitar un recurso al servidor mediante una petición URL en sus métodos variantes GET, POST, PUT, DELETE, entre otros.

Una petición URL estructura el protocolo que puede ser HTTP o HTTPS, luego el dominio y puerto y la ruta del recurso, por ejemplo.

http://localhost:3000/api/v1/users

La petición también dispone de estructuras básicas para la transmisión de datos variables, por ejemplo, filtros de búsqueda, credenciales, tokens, entre otros. Esto se logra en las peticiones de tipo GET mediante los parámetros expuestos listados o mejor conocidos como la consulta de la petición y son expuestos dentro de la misma url mediante parejas de claves y valores separados por el signo de igualdad y unidos por un ampersand. Como se muestra en el siguiente ejemplo.

http://localhost:3000/api/v1/usuers/search?q=Ana&limit=10

La transmisión de datos de la petición del cliente al servidor de los recursos también podría darse en un formato especial de datos como XML, JSON, entre otros. En el siguiente ejemplo, se muestra una petición nativa de un cliente Javascript usando fetch y el método POST.

Cuándo definimos un API debemos pensar en qué tipo de datos recibirá el servidor en la petición, en el ejemplo anterior supusimos que el servidor era capaz de aceptar un cuerpo de datos en formato JSON. También debemos de pensar en qué tipo de datos regresará como respuesta el servidor, en este caso asumimos que el servidor nos responderá siempre (en caso de salir bien la petición) con una estructura JSON.

Observa del ejemplo anterior que usamos !reponse.ok para verificar si el servidor no tuvo problemas con nuestra petición (estatus 200 OK), en este sentido, debemos ser sensibles al momento de programar nuestro servidor y normalizar las entradas y salidas, pero también manejar algunos estatus bien conocidos del protocolo HTTP, como 200 (ok), 400 (bad request), 401 (unauthorized), 500 (internal server error), entre otros.

Una vez que logramos establecer un API estable es importante considerar que el API va a ser mantenido en su ciclo de vida, esto implica prepararnos para dejar de dar soporte a una versión que tenga inseguridades, reparar una versión defectuosa o agregar funcionalidad mejorada y una nueva estructura y versión.

Generalmente basta con usar la base /api/vX.Y y mandar alertas que le notifiquen al programador que pronto quedará obsoleta una versión.

La parte más difícil de programar una API es generar toda la documentación para que los programadores sepan cuál es el funcionamiento y los parámetros de entrada y salida, algunos casos de ejemplo y referencias a otros módulos del API. Generar toda esta documentación al mismo tiempo que se programa es un infierno si no se usa la estrategia adecuada. Una forma de generar una buena documentación al mismo tiempo que se programan las pruebas unitarias puede ser generar un archivo de texto del cuál se extraigan las pruebas unitarias que se van a realizar.

Anteriormente se usaban documentadores como JSDoc los cuáles mediante comentarios dentro del código generan automáticamente la documentación. Sin embargo, esto es muy fácil de lograr si hacemos el proceso inverso, es decir, si partimos de un archivo Markdown por ejemplo, y de ahí extraemos las pruebas unitarias. Algo así como crear un documento de texto y de ahí extraer el código para realizar las pruebas unitarias. El siguiente documento muestra una idea breve.

Este tipo de técnicas nos ayudan a dejar una documentación libre y consistente la cuál sólo requiere algunas expresiones regulares para extraer los casos de ejemplo y evaluarlos automáticamente. Con la ventaja que se puede documentar libremente, por ejemplo, incluir imágenes, referencia a documentación, ecuaciones matemáticas, tablas, entre muchas más cosas.

La iniciativa de Open API (https://github.com/OAI/OpenAPI-Specification) es un proyecto de la comunidad que pretende crear un modelo base para las peticiones del API Rest. Es decir, es una intención de estandarizar un esquema en el que se deberían llamar en general a los API Rest programados a lo largo de diversos proyectos, ya que es muy común encontrar disparidad entre los esquemas que utiliza un equipo de desarrollo y otro para sus llamadas Rest.

Lo importante aquí es notar que la evolución del API precisamente pretende en generar modelos estándares en los que el programador se sienta libre de explorar las API y tener la documentación a la mano. Una buena forma de hacerlo (no menos tediosa para quién programa el API), es que en las peticiones el programador pueda solicitar el esquema del API, es decir toda su documentación y ejemplos en una llamada especial o al provocar un error, por ejemplo.

http://localhost:3000/api/v1.0/users/@

Mostraría la documentación del API, así el programado que desee consultar la documentación principal tendría que hacer.

http://localhost:3000/api/v1.0/@

O incluso, podría obtener toda la documentación de todas las versiones del API.

http://localhost:3000/api/@

De esta manera, los programadores podrían ir explorando el API a profundidad de forma fácil sin desperdiciar tiempo en aprender toneladas inútiles de documentación. Usando una lógica más guíada podrían incluso ir directamente a las pruebas unitarias para ver como funcionan.

http://localhost:3000/api/v1.0/users/posts/search/@test-1

Y en la programación sólo bastaría con agregar una ruta extra hija de la principal.

Finalmente, es importante hablar acerca de la capacidad del API de ser reciclada en estructuras fuera del API Rest. Un ejemplo, es poder utilizar un mismo API en Rest bajo métodos GET o POST, usarlo también en Sockets y quizás como módulos nativos del lenguaje de programación.

La idea es construir meta-módulos que sean capaces de aceptar una entrada y un controlador y producir una salida mediante ese controlador, dónde el controlador pueda ser sustituido por un controlador HTTP, Socket, Función Nativa, Base de Datos, entre otros.

Con esto aproximamos la idea de tener una plataforma de API en Grafo capaz de operar entre distintos controladores y módulos nativos del lenguaje de programación, sin estar adaptando la funcionalidad base del API.

Con esto logramos conectar APIs definidas para diversos controladores internos y tenemos la capacidad de exportar toda esa funcionalidad al usuario final. Es decir, imagina que defines un API que consulta registros de la base de datos, indicando como entrada el nombre de la base de datos, el nombre de la colección o tabla y los parámetros de búsqueda y el motor de base de datos, entonces, luego defines otra API encargada de obtener una lista de dataframes y generar un reporte PDF, así, fácilmente se podrían conectar ambas API en un mismo flujo con diferentes controladores, por ejemplo, la entrada para hacer la consulta a la base de datos podría venir de otra API intermedia que es llamada bajo el controlador HTTP y una petición REST, pero internamente en lugar de devolver los resultados por REST envía los datos directamente al otro API que genera el PDF y los datos de salida son envíados por el controlador Socket.IO para notificarle al usuario que tiene un PDF pendiente, todo esto al mismo tiempo que en REST se devuelve la respuesta de toda la ejecución.

Este tipo de arquitecturas abren un nuevo mundo por explorar y las capacidades son infinitas. Imagina interceptar un API y hacer que continue hasta que un usuario llene un formulario, pase un evento, se confirme un correo electrónico, o termine una descarga.

--

--

Alan Badillo Salas
big-data-for-humans

L. Matemáticas Aplicadas UAM-Cuajimalpa. M. en Inteligencia Artificial IPN-CIDETEC. Desarrollador Full Stack MEAN/MERN. Data Scientist.