Diseñando APIs RESTful

¿Por qué este post? 

Tras bastantes años investigandopublicandoconsumiendo e, incluso, dando formación o impartiendo webinars sobre ello, sigo recibiendo preguntas o leyendo cosas en foros que me dejan ojiplática y que me dan muchas ganas de publicar un post como éste. Incluso, hay quien dice que su API es RESTful y luego lo escribe así: RESTfull... por lo que empecemos por el principio.

 

En 2011 ya usaba Servlets Java que recibían JSON. Luego conocí los controladores en Spring y, más tarde, los controladores REST con SpringBoot. Está claro que la evolución Web va en esa dirección, en busca del consumo de APIs ligeras y el desacoplamiento con las capas cliente.  

 

Pero no queremos saber cómo funciona a bajo nivel

Aún con las “ayudas” de los frameworks, y pongo “ayudas” entre comillas porque muchas veces lo que consiguen es que no sepamossi no queremos, lo que hay por detrás (como un protocolo HTTP estupendo), seguimos haciendo APIs poco amigables y RESTless, sin utilizar los estándares que se van haciendo innegablemente necesarios cuando el número de este tipo de servicios, y de sus consumidores, va en aumento casi a diario. 

 

Tampoco hay nada que nos obligue a hacerlo de una manera concreta, lo cual tiene su parte buena: es totalmente flexible; y su parte mala: porque cada uno lo hace como quiere

Si el código compila y no hay nada ni nadie que nos impida hacer un servicio a nuestro libre albedrío, podría tomar como normal que, al principio de su uso, cada uno lo hagamos a nuestra manera. Pero ya no es el caso, ahora tenemos mucha más experiencia como consumidor y/o publicador como para darnos cuenta de lo que aporta un API bien hecha, tanto como cliente a la hora de integrarla como para poder mantenerla y extenderla. 

Y para más inriexistiendo documentación extensa de cómo funciona el protocolo en el que basa. 

 

Hoy ya no es ayer, el mundo web es nuestro

Antes (y me siento viejuna), los servicios se hacían para un cliente concreto, que normalmente se solía implementar por gente cercana... o hacíamos servicios que tenían que tener tal interfaz para cumplir lo que el cliente ya estaba consumiendo y reducir el impacto. A día de hoy, las APIs se implementan por un lado y tenemos clientes desperdigados por el mundo que las consumen. Hay que cambiar el chip y ser consciente de que el mundo web es para todos, fomentando estar conectados. ¿No creéis que tiene sentido facilitarlo de alguna forma? 

 

Por todo eso y porque me duele ver, a día de hoy, una nueva API hecha sin cariñoos quiero mostrar una forma de diseñar APIs RESTful (o pragmatic, al menos) y, lo más importantetodos los motivos que me llevan a hacerlo de esa manera y no de otra. 

 

Conceptos básicos

Como ya mencionabatrabajamos con Internet que se basa en el protocolo HTTP. Aunque me digáis que soy una friki, es muuuy importante conocer con lo que tratamos día a día, por lo que os dejo un link a las especificaciones que se definieron en el RFC de HTTP 1/1 que tanto usamos (https://tools.ietf.org/html/rfc2616). Os animo a echarle un ojo y a que me digáis si no os asombra que conteste muchas de las preguntas que nos seguimos haciendo cuando estamos diseñando un API, incluso indicando cómo DEBE utilizarse concretamente, no de forma abstracta. 

Por ejemplovemos párrafos como el siguiente hablando de los métodos HTTP, donde nos dicen claramente para lo que sirven (operación a realizar sobre el recurso identificado en la URI) y cómo hay que indicar al cliente (en cuanto a métodos disponibles) los diferentes casos que se pueden dar: 

 

Solamente es un ejemplo de todo lo que ya se ha pensado y documentado. ¿Por qué inventar o hacerlo como nos parece?  ¿Por qué no partimos de una base de la gente que ha creado nuestra herramienta de comunicación? ¿Por qué acabamos conociendo bien el API de Java o de .NET, pero no esto? No  si por desconocimientodesganaayudas que te alejan de lo que haces o poco cariño diseñando... sólo espero que sirva como reflexión y entendáis la importancia que veo en seguir unas pautas que, curiosamenteya existenpero que nadie te obliga forzosamente a seguir. 

Siendo diseñador de APIs puedo tomar esta documentación como referencia a la hora de implementarlas; y como cliente consumidor¡¡también!!. Es algo más ágil y estándar que tener que ir a preguntar al que ha hecho el API, ¿verdad? 

 

Quizá me he puesto un poco tostón con el RFC, así que voy a intentar aligerarlo resumiendo unos conceptos básicos para esta primera entrega, pero muuuy a tener en cuenta en todo momento: 

 

Orientado a recursos

Recurso: cuando diseñamos APIs, tenemos que orientarlas a recursos. Es decirdejemos de pensar en las entidades que tenemos en base de datos y pensemos en entidades con funcionalidad por  mismas de cara a un usuariopensemos en recursos

Antes hacíamos CRUD de tablas de bbddahora hacemos CRUD de Recursos (que normalmente tienen datos de varias tablas de nuestro modelo de entidades). 

Con esta forma de pensamiento, surge la necesidad de tener subrecursos. Por ejemplo, un contacto no tiene funcionalidad por  mismo si no hay un usuario asociado; o un movimiento entre cuentas no puede existir sin una cuenta origen, que no puede existir a su vez sin un cliente y/o contrato. De esta forma podemos ir diseñando los recursos y subrecursos que necesitaremos exponer en nuestra happyAPI y, por tanto, las URIs. 

 

URIs amigables y entendibles

URI: Universal Resource Interface; o, lo que es lo mismo, endpoint o URL relativa con la que acceder a cada recurso. Y sabiendo ya que hablamos de recursos y subrecursospodríamos tener algunas URIs como las siguientes: 

/customers/ 

/customers/1/accounts/2/movements 

/users/ 

/users/225369/contacts 

 

Así, sin explicar nada, ¿sabríais interpretar qué representa cada una? Probablemente ... vosotros y cualquiera que necesite consumir nuestra API.  

Es cierto que la decisión de qué es subrecurso o cómo acceder a él muchas veces genera discusióno la forma de facilitar el acceso a los datos  para no tener una URI que sobrepase los límites de 255 caracteres. Por ejemplo, igual preferimos recuperar todos los contactos de cualquier usuario (raropero es nuestra API y exponemos la funcionalidad que creemos necesaria), con lo que tendríamos: 

/contacts  

En la respuesta, para cada contacto, se debería linkar con el usuario propietario para que el API sea útil, pero así podríamos acceder directamente a toda la lista de contactos existentes.  

 

NOTA: Como veis, no siempre es sencillo tomar determinadas decisiones¡todo compila!. Pero, desde mi experiencia, a no ser que tengamos una jerarquía infernal de recursos, lo suyo es anidarlos para acceder desde los recursos principales a los diferentes subrecursos, de forma que sea mucho más amigable y entendible simplemente viendo la URI que lo referencia. 

Así también podremos utilizar mecanismos como el “expand”, que sirve para indicar si queremos que en la respuesta nos devuelva toda la información de determinados subrecursos o solamente la URI relacionada para obtenerlos en otra petición. 

 

Uso correcto de métodos HTTP

Método HTTPotra parte importante de un API es la definición de los métodos HTTP para consumirla. He visto cosas que no creeríais...  

Scared Dog GIF

En la imágen del RFC se ven algunos de los métodos más utilizados. Los más importantes y que nos deben sonar bastante son POST, GET, PUT, PATCH y DELETE.

Cada unoademáspodemos asociarlo fácilmente con una acción de los típicos CRUD de recursos (Create, Read, Update, Delete), respectivamente 

Peeeero cierto es que todo compila y que aunque se llame con un POST, puede que, en la implementación del API, estemos borrando el recurso

Como todonecesitamos aplicar sentido común, y en este caso es sencillo implementar nuestra API como manda el paradigma RESTful: 

 POST   Crear recurso
 PUT   Actualizar recurso completo
 PATCH   Actualizar parte del recurso
 GET   Recuperar uno o varios recursos
 DELETE   Eliminar recurso

 

 

Uso correcto de códigos HTTP

Código HTTP: igual de importante es usar el método HTTP que indica el protocolo, como sus códigos. Tenemos muchos disponibles, y cada uno con su significado concreto, ¡¡usémoslos!!

Los códigos están agrupados en cinco bien diferenciados, según su sentido:

 

Además de tener dichos grupos genéricos, también definieron códigos concretos (con su documentación en diferentes secciones), como por ejemplo:

   

 

Con estos conceptos claros, ya tendríamos lo mínimo para poder crear una interfaz de API REST siguiendo el paradigma RESTful.

 

De momento, nos sirve para ir viendo por dónde van a ir los tiros... ¡espero que sirva para la reflexión y que no os perdáis las siguientes entregas!

 

¡¡Be RESTful my friend!!