¿Qué es una API REST?

El diseño de APIs REST o RESTful (transferencia de estado representacional) permite aprovechar los protocolos existentes. Si bien el modelo REST se puede usar con prácticamente cualquier protocolo, normalmente se puede aprovechar el protocolo HTTP para las API web. De esta forma, los desarrolladores no tienen que instalar bibliotecas ni software adicional para aprovechar el diseño de APIs REST. El diseño de APIs REST fue definido por Roy Fielding en su tesis doctoral del año 2000. Destaca por su extraordinaria capa de flexibilidad. Como los datos no están limitados a métodos y recursos concretos, REST es capaz de gestionar numerosos tipos de llamadas, devolver diferentes formatos de datos e incluso realizar modificaciones estructurales con una implementación correcta de hipermedia.

La libertad y la flexibilidad inherentes al diseño de APIs REST permiten desarrollar una API que satisfaga tanto las necesidades de la organización como las de los clientes más diversos. A diferencia de SOAP, REST no se limita a XML, ya que puede devolver XML, JSON, YAML o cualquier otro formato en función de los que desee el cliente. También contrasta con RPC, ya que los usuarios no están obligados a conocer los nombres de los procedimientos ni los parámetros específicos en un orden concreto.

No obstante, el diseño de APIs REST tiene algunos inconvenientes. Es posible perder la capacidad de mantener un estado en REST (por ejemplo, dentro de las sesiones), y puede resultar más difícil de usar para los desarrolladores novatos. También es importante entender qué factores hacen que una API de REST sea RESTful y por qué estas limitaciones son previas al desarrollo de la API. Al fin y al cabo, si no se entiende por qué algo está diseñado de una forma concreta, el proceso puede verse afectado negativamente de forma inadvertida.

Entender el diseño de APIs REST

Si bien se dice que la mayoría de las API son RESTful, a menudo incumplen los requisitos y las limitaciones establecidos por Roy Fielding. Existen seis limitaciones clave en el diseño de APIs REST que deben tenerse en cuenta al decidir si se trata del tipo de API correcto para un proyecto.

Cliente-servidor

La limitación cliente-servidor parte de un concepto según el cual el cliente y el servidor deben ser independientes entre sí y capaces de evolucionar de forma individual y separada. En otras palabras, uno debe tener la opción de realizar modificaciones en una aplicación móvil sin que ello afecte a la estructura de datos ni al diseño de la base de datos en el servidor. Al mismo tiempo, el diseño debe permitir modificar la base de datos o la aplicación del servidor sin que el cliente móvil se vea afectado. Esta circunstancia crea una separación de las preocupaciones, ya que cada aplicación puede crecer y escalarse independientemente de la otra, y permite que las organizaciones crezcan rápida y eficientemente.

Sin estado

Las API REST carecen de estado, lo que significa que pueden realizarse llamadas independientes entre sí y que cada una contiene todos los datos necesarios para completarse correctamente. Una API REST no debe depender de datos almacenados en el servidor o en sesiones para determinar qué hacer con una llamada, tiene que poder responder solo en base a los datos que se facilitan en la propia llamada. La información de identificación no se almacena en el servidor al realizar llamadas. En su lugar, cada llamada contiene los datos necesarios, como la clave de API, el token de acceso, el ID de usuario, etc. Al disponer de todos los datos necesarios para realizar la llamada, se incrementa la fiabilidad de la API, pues no depende de una serie de llamadas con estado de servidor para crear un objeto, algo que puede provocar errores parciales. Así, para reducir los requisitos de memoria y conseguir la mayor escalabilidad posible para las aplicaciones, una API RESTful requiere que todos los estados se almacenen en el cliente y no en el servidor.

Caché

Puesto que una API sin estado puede incrementar la sobrecarga de solicitudes al gestionar grandes cantidades de llamadas entrantes y salientes, las API REST deben diseñarse de forma que fomenten el almacenamiento de datos en caché. Ello significa que, cuando los datos son almacenables en caché, la respuesta debe indicar que esto será así hasta una hora determinada (caducidad); no obstante, si se requiere que los datos sean en tiempo real, debe indicarse que el cliente no puede almacenar la respuesta en caché. Al habilitar esta limitación fundamental, no solo se reduce el número de interacciones con la API (y con ellas el uso interno del servidor), también se proporcionan a los usuarios de la API las herramientas necesarias para entregar las aplicaciones más rápidas y eficientes posibles. Hay que recordar que el almacenamiento en caché se realiza en el lado del cliente. Si bien se pueden almacenar algunos datos en caché dentro de la arquitectura para mejorar el rendimiento general, el objetivo es informar al cliente de cómo debe proceder y comunicarle si puede almacenar datos temporalmente o no.

Interfaz uniforme

La clave para desvincular al cliente del servidor es contar con una interfaz uniforme que permita la evolución independiente de la aplicación sin necesidad de que sus servicios, modelos o acciones estén estrechamente vinculados a la capa de APIs. La interfaz uniforme permite que el cliente hable con el servidor en un único lenguaje, independiente del backend de arquitectura de ambos. Así, proporciona un medio estable y estandarizado de comunicación entre el cliente y el servidor, como el uso de HTTP con recursos de URI, CRUD (crear, leer, actualizar y eliminar) y JSON.

Sistema con capas

Como su nombre indica, este tipo de sistema se compone por capas, donde cada una tiene una función y responsabilidad específicas. Por ejemplo, en el marco de trabajo Modelo-vista-controlador, cada capa tiene sus propias responsabilidades: los modelos indican cómo deben formarse los datos, el controlador se centra en las acciones entrantes y la vista se encarga de la salida. Cada capa es independiente, pero también interactúa con las demás. En el diseño de APIs REST, se aplica el mismo principio, ya que diferentes capas de la arquitectura trabajan juntas para montar una jerarquía y, con ella, aplicaciones más escalables y modulares.

Un sistema con capas también permite englobar sistemas heredados y transferir funciones de acceso menos habitual a un intermediario compartido, lo que supone también una mejor protección para los componentes más modernos y utilizados. Asimismo, el sistema con capas otorga la libertad necesaria para incluir y excluir sistemas en la arquitectura a medida que las tecnologías y los servicios evolucionan, lo que aumenta la flexibilidad y la longevidad si se mantiene una conexión lo más holgada posible entre los diferentes módulos. En lo que respecta a la seguridad, disponer de un sistema con capas presenta claras ventajas, ya que permite detener ataques en la capa de proxy o en otras capas, evitando así que alcancen la arquitectura propia del servidor. Al utilizar un sistema con capas y proxy, o al crear un punto único de acceso, es posible mantener los aspectos esenciales y más vulnerables de la arquitectura tras un cortafuegos, lo que evita la interacción directa del cliente con ellos. Hemos de tener en cuenta que la seguridad no se basa en una solución única contra todo, sino en contar con varias capas entendiendo que ciertos controles de seguridad pueden fallar o ser sorteados. Así, a mayor seguridad implementada en un sistema, mayor será la probabilidad de evitar ataques dañinos.

Código bajo demanda

El código bajo demanda, quizá la menos conocida de las seis limitaciones y la única que es opcional, permite transmitir código o applets a través de la API para su uso dentro de la aplicación. En esencia, crea una aplicación inteligente que ya no es enteramente dependiente de su propia estructura de código. No obstante, quizá por estar adelantado a su tiempo, el código bajo demanda ha tenido problemas de adopción, ya que las API web se consumen en diferentes lenguajes y la transmisión de código incrementa las preguntas y preocupaciones de seguridad. (Por ejemplo, el directorio tendría que admitir la escritura, y el cortafuegos tendría que dejar pasar contenido que normalmente bloquearía).

En conjunto, estas limitaciones conforman la teoría de la transferencia de estado representacional (REST). Al analizarlas, observamos que cada una se basa en la anterior, dando lugar a una interfaz de programación de aplicaciones bastante compleja, pero también potente y flexible. Y lo que es más importante: estas limitaciones componen un diseño que funciona de manera similar a como accedemos a las páginas web desde los navegadores. Permiten crear una API que no está controlada por su arquitectura, sino por las representaciones que devuelve; una API que, si bien carece de estado de arquitectura, depende de la representación para dictar el estado de la aplicación.