REST


Están muy de moda las API que dicen ser REST, pero en lo único que tienen son URLs lindas.

Pongamos algo en claro: tener URLs lindas no hace una API REST. Que sea HTTP no la hace REST. Que use los métodos que corresponden no la hace REST.

Si tenemos que reducir la verificación de si algo es REST al elemento más simple, podemos empezar por una pregunta: ¿Un recurso tiene links a los otros recursos?

Si la respuesta es “No”, entonces NO ES REST.

La API de Twitter no es REST. Supongamos que queremos ver un tweet particular. Para eso tenemos que hacer una request a

GET statuses/show/:id

Linda URL. Clara, directa… Debe ser REST, ¿no?

No.

¿De dónde salió ese ID? ¿Por qué me dio un ID en vez de una URL?

Antes de hacer la request del tweet hubo una request anterior para la autenticación del usuario. El último paso de la autenticación nos da varios valores; pero en muchos casos se usa como si sólo se pudieran mandar los relacionados a la autenticación. ¿Por qué no incluir datos del usuario? El más obvio es la URL del perfil (también podríamos incluir la URL de su página principal… y de ahí más links, por ejemplo, hacia cada uno de los tweets en su perfil). El ID igualmente lo teníamos que haber leído de alguno de esos lugares: de la misma lista de Tweets del perfil. En vez de solo poner un ID, ponemos un link al tweet.

Las URLs son los nuevos IDs

HATEOAS (Hypermedia As The Engine Of Application State) es uno de los pilares de REST. Nos dice que el Estado de la aplicación se altera mediante los vínculos provistos. Casi como si el recurso fuera un objeto en el cual llamamos a un método. Es el mismo objeto el que nos dice: “Para borrarme, mandá un DELETE a esta URL”, en vez de tener que encontrar un método de borrado al cual le pasamos un ID.

Pero, ¿por qué es tan malo tener que armar las URL?

  • Estamos multiplicando el trabajo:

    Si NO devolvemos un link…

    • El creador de la API parsea el link para generar el contenido.
    • El creador lo documenta “fuera de banda”
    • Cada cliente tiene que armar su propio link.

    Mientras que si el creador de la API nos pasa un link…

    • El creador de la API parsea el link
    • El creador de la API genera el link (típicamente usando el mismo router para las dos cosas)
  • Estamos exhibiendo valores innecesariamente. Las URLs bien armadas sin duda son lindas, pero un servicio REST podría funcionar perfectamente si todas las URLs apuntaran a UUIDs.

    Si en un sitio sabemos que la última respuesta que nos dieron está en .../respuestas/12345, es extremadamente fácil probar .../respuestas/12344 a ver si encontramos algo. En cambio, si estuviera en .../respuestas/021979ef-e183-4bb5-9dcf-28d4e0508c3f, ¿qué probamos?

    Parece una simple capa de seguridad por oscuridad (especialmente si usamos un caso levemente más realista donde el ID es aleatorio, pero corto), pero también ayuda a prevenir que se filtre cierta información, como “¿Cuantas transacciones hizo este usuario?” o “¿Cuantos usuarios tiene el sitio?”

  • La API sin links es más difícil de explorar. En la API con links, cada request nos apunta a las demás acciones que podemos tomar: “Tomá el Tweet. Si querés borrarlo, andá acá; si querés retweetearlo andá acá; si querés más detalles del usuario, andá acá”.

Por supuesto, los links no son el único factor; solo que son el que más veo abusado por ahí. Demasiadas APIs que dicen ser REST pero no respetan uno de los elementos centrales, que es el hypermedia.

Una API REST debe:

  • Publicar recursos (no llamadas a procedimientos).
  • Vinculados entre sí (links; no IDs).
  • Que se modifican utilizando los métodos apropiados (GET, POST, PUT, DELETE, etc.).

Si falla esas características no necesariamente es una “mala” API; solo que no es REST.