En la actualidad existen muchas tecnologías para publicar servicios y componer una arquitectura cliente-servidor. ReST es probablemente la más extendida y es difícil encontrar un sitio en el que no se esté usando. En este post veremos las bases de ReST y explicaremos como diseñar un api que sea aceptablemente ortodoxa.
Cables azules para las peticiones GET. Cables blancos para las POST |
El protocolo HTTP
La idea que hay detrás del
protocolo HTTP es sencilla y particular: en un servidor existen una serie de
recursos guardados en directorios reales o imaginarios. Después los clientes
envían peticiones en las que se incluye una ruta a uno o varios de esos recursos
junto con un verbo que indica que acción debe realizarse una vez estos hayan
sido localizados.
Otras características de HTTP que
lo hacen muy conveniente como protocolo de comunicación entre cliente-servidor
son:
- Mensajes sencillos: Los mensajes HTTP son textos planos con apenas estructura. Una cabecera con información sobre la petición y un cuerpo opcional. Es tan sencillo que la separación entre cabecera y cuerpo son dos saltos de línea y retorno de carro seguidos.
- Independiente del formato de la información intercambiada. Puede ser xml, json, una imagen, html o cualquier cosa que se nos pase por la cabeza.
- Sin estado: La conversación más larga que puede mantenerse con HTTP es petición-respuesta, precisamente porque HTTP está pensado para aplicaciones distribuidas que trabajan con los recursos alojados en un servidor. El servidor no almacenará estado alguno ni dedicará recursos en ello (por ejemplo creando sesiones). Si es necesario mantener un estado esta tarea recaerá sobre las aplicaciones cliente.
Esta última característica tiene
una gran importancia a la hora de diseñar un api ReST y todas las
funcionalidades que ofrezca el servidor deberán tenerla en cuenta.
ReST
De Representational State Transfer, es una arquitectura de software para aplicaciones cliente-servidor
ideada por Roy T. Fielding cuya principal característica es que utiliza el
protocolo HTTP hasta la última consecuencia. Toda la información que maneje el
servidor será representada como recursos y cualquier funcionalidad ofrecida por
este deberá poder accederse a través de una petición HTTP que respete los
principios del protocolo al pie de la letra.
Roy T. Fielding diciendo lo que es ReST y lo que no. |
Los recursos
Lo primero que definiremos cuándo
diseñamos un api ReST son los recursos. Estos serán la información que maneje
nuestro servicio. Ejemplos típicos (y tópicos) de recursos podrían ser
clientes, facturas, productos, empleados... Cada uno de estos recursos deberá
identificarse con un valor único y poseerá distintas propiedades. Por ejemplo:
los clientes tendrán id, nombre, DNI, fecha de nacimiento y los productos id, referencia,
fabricante, peso, etc.
Decidir cuáles son los recursos
resulta más sencillo cuando ya disponemos de una base de datos o la lógica de
la aplicación. Es la norma que exista una relación entre las tablas que tengamos
y los recursos del servicio. Esto también ocurrirá con respecto a las entidades
que utilice nuestra lógica de negocio. Además descubriremos que las relaciones
entre esas tablas o entidades se ve reflejada en las relaciones existentes
entre los recursos. Pero no nos confundamos: ¡un api ReST es una abstracción
que a simple vista nada tiene que ver con un diagrama de clases o de
entidad-relación!
La representación de los recursos
Una vez identificados los
recursos debemos decidir cómo los representaremos en las peticiones y
respuestas. HTTP permite cualquier formato, pero normalmente podremos escoger
entre XML y JSON debido a que los frameworks suelen tener en cuenta únicamente esos dos formatos. Si escogemos otra
manera de representar a los recursos nos tocará hacer las debidas conversiones
con nuestro propio código.
La inmensa mayoría de servicios
ReST trabajan con JSON puesto que contienen la misma información que un XML
pero son más sucintos, a costa de no incluir ninguna descripción de la
información que contienen. Veámoslo con un ejemplo:
Lucha de acrónimos |
En el XML vemos que hay
claramente una lista de clientes. En JSON básicamente sustituimos cada etiqueta
xml por un único carácter. Cierto que no queda claro que se trate de clientes y
bien pudieran ser ‘empleados’ o ‘personas’ pero no debemos olvidar que en un
servicio ReST tenemos una aplicación cliente que es capaz de saber que está
solicitando un listado de clientes, no de empleados. El XML en este caso es un despilfarro
de ancho de banda.
Las rutas
El siguiente paso una vez que
conozcamos cuáles son nuestros recursos será definir las rutas para
localizarlos. Debemos ‘colocarlos’ en esos directorios de los que nos habla el
protocolo HTTP y es el momento de hacer un inciso relacionado con ellos.
En HTTP localizamos los recursos
utilizando URLs. Con una URL identificamos un recurso, su localización y el
modo en el que accederemos a él.
En la ruta encontramos los
directorios en los que se localiza el recurso identificado por el valor final.
Cuando se trata de recursos físicos esos directorios existen realmente. Es lo
que sucede, por ejemplo, con un servidor web. En Apache (el servidor web más utilizado) disponemos del directorio
‘www’ dentro del cual organizamos nuestros ficheros .html, .css, imágenes y
demás cacharrería. Cuando los recursos son abstractos, representaciones de
filas en una tabla u objetos en la memoria del servidor, los situaremos en
directorios ficticios para ‘seguirle el juego’ al protocolo HTTP.
Recursos físicos en un servidor Apache de color azul |
Una técnica que nos ayuda a
definir las rutas es imaginarnos los recursos realmente como ficheros y
realizarnos la siguiente pregunta: Si tuviera una serie de ficheros, a razón de
uno por ‘Empleado’ ¿en qué directorio los guardaría? ¿Y si fueran facturas,
productos o cualquier otra cosa? La respuesta es clara: en los directorios
‘empleados’, ‘facturas’ y ‘productos’.
Los métodos
En HTTP una petición es una ruta
a los recursos más una acción, el método. De todos los métodos definidos en
HTTP los cinco que sirven para actuar sobre los recursos son
- GET: se solicitan recursos existentes en el servidor
- POST: añade un nuevo recurso en la ruta indicada
- PUT: Sustituye el recurso indicado por la url por el que se envía. Si no existe lo añadirá.
- PATCH: Modifica el recurso utilizando los datos adjuntos a la petición.
- DELETE: Elimina los recursos indicados en la url.
En realidad los métodos no hacen
nada…todo depende de la implementación del servicio en el lado del servidor.
Vamos a suponer que nadie programará que al recibir un GET se elimine un
recurso y que cuando se reciba un DELETE se entregen. Suena absurdo, pero es
perfectamente posible hacerlo así.
Con esto ya tenemos la base de que es un servicio ReST. En el siguiente post comenzaremos con el diseño de un api sencilla.