24 puntos por GN⁺ 2025-07-10 | 1 comentarios | Compartir por WhatsApp
  • En el artículo original de REST de Roy Fielding, no se establece explícitamente el uso de métodos HTTP ni de API centradas en CRUD, y REST originalmente pone énfasis en el diseño de sistemas basados en hipermedia (HATEOAS)
  • Muchas de las interfaces que la gente llama API RESTful no implementan restricciones importantes de REST (especialmente el uso de hipermedia)
  • Un recurso no se limita a una simple estructura de datos o entidad, sino que incluye cualquier concepto que pueda identificarse con un URI
  • Según las 6 reglas de Fielding, lo esencial es la navegación centrada en hipermedia, la independencia del protocolo y la importancia de los tipos de medio
  • En la práctica, debido a la conveniencia de herramientas de documentación como OpenAPI, la mayoría de las API tienden a diseñarse más cerca de un estilo RPC que de algo verdaderamente RESTful

Por qué la mayoría de las API RESTful no son realmente RESTful

  • El artículo de referencia (2000) de Roy Fielding presenta REST (Representational State Transfer) como un estilo ideal de diseño para software en red y lo explica como el principio que sostiene el éxito de la web
  • El artículo no exige como algo indispensable el uso de métodos HTTP ni un diseño centrado en CRUD; al buscar REST, enfatiza que lo central es la transición de estado basada en hipermedia (HATEOAS), una interfaz uniforme y la interacción centrada en recursos

Hipermedia (HATEOAS) y los malentendidos sobre REST

  • Fielding señala claramente que una API sin hipermedia no es RESTful
    • "Si el motor no es impulsado por hipervínculos, no es RESTful"
  • HATEOAS es un enfoque en el que el cliente descubre dinámicamente las acciones siguiendo enlaces incrustados en las respuestas del servidor
  • Usar simplemente una interfaz HTTP/CRUD no equivale a la esencia de REST

Malentendidos comunes sobre REST

  • La idea de que REST es CRUD (en realidad es un concepto más amplio)
  • El malentendido de que los recursos son entidades (estructuras de datos del servidor)
  • La afirmación de que una API RESTful no debe usar verbos
  • Todo eso son solo decisiones de diseño y no está directamente relacionado con la esencia de REST

El significado real de una arquitectura guiada por hipermedia (HATEOAS)

  • El objetivo de HATEOAS es minimizar el acoplamiento cliente-servidor
  • Cuando cambia la estructura de URI del servidor, reduce el dolor de tener que volver a desplegar clientes y mejora la escalabilidad y la capacidad de evolución
  • El cliente descubre cómo actuar siguiendo los hipervínculos dentro de la respuesta, sin documentación ni conocimiento previo
    {  
      "orderId": 123,  
      "_links": {  
        "self": { "href": "/orders/123" },  
        "cancel": { "href": "/orders/123/cancel", "method": "POST" }  
      }  
    }  
    
  • Como en el ejemplo anterior, para acercarse a algo verdaderamente RESTful, la respuesta debe incluir acciones (enlaces)

¿Qué es un recurso en REST?

  • Un recurso es cualquier cosa identificable mediante un URI
    • Incluye documentos, imágenes, objetos físicos, servicios, conceptos abstractos, etc.
  • En el servidor no existe necesariamente un “recurso” como objeto real; más bien existe una estructura abstracta de mapeo accesible mediante URI
  • Incluso en RFC 3986 no se limita el alcance de lo que puede ser un recurso
    • Puede incluir documentos electrónicos, imágenes, fuentes de información, servicios e incluso personas, entidades legales o libros

Las 6 reglas de una API RESTful definidas por Fielding

  • 1. No depender de un solo protocolo
    • La identificación basada en URI debe poder aprovecharse en cualquier protocolo
  • 2. No alterar arbitrariamente los estándares del protocolo (por ejemplo, HTTP)
    • Se puede complementar lo que falte en el estándar, pero no agregar ni cambiar reglas de forma arbitraria
  • 3. Enfocarse en definir tipos de medio (formatos), no en la estructura de URI
    • Hay que concentrarse en el formato de los datos y la definición de enlaces, no desperdiciar energía en especificar o documentar rutas
  • 4. No codificar rígidamente nombres de URI ni jerarquías fijas
    • Para evitar que el cliente adivine o fije la estructura del espacio de nombres del servidor, debe inducirse una navegación basada en enlaces
  • 5. No exponer los tipos de recurso (clasificación interna)
    • Los tipos internos de objetos no tienen significado para el cliente; solo deben exponerse tipos de medio estándar y enlaces
  • 6. Solo se necesita un marcador inicial (URI inicial); el resto debe descubrirse por los enlaces de la respuesta
    • El cliente solo conoce tipos de medio estándar, y las transiciones de estado siempre deben realizarse con base en hipervínculos dentro de la respuesta del servidor

Interpretación de las reglas y aplicación práctica

  • Para acercarse a algo verdaderamente RESTful, hay que minimizar el acoplamiento al protocolo, al URI y a los tipos
  • La API debe enfocarse en el formato de los datos y de los enlaces (tipos de medio), y el cliente no necesita conocer de antemano la estructura del URI ni las reglas de nombrado
  • En lugar de especificar una ruta como /users/123/activate, como en el ejemplo, la acción debe guiarse mediante un enlace "activate" dentro de la respuesta

Por qué las API realmente RESTful son poco comunes

  • La conveniencia de herramientas como OpenAPI y Swagger suele tener prioridad en el trabajo de desarrollo
    • Ofrecen ventajas reales como documentación automática, generación de código y validación
  • En entornos SPA donde cliente y servidor son desarrollados por el mismo equipo, la necesidad de resolver el problema del acoplamiento por URI no es tan grande, por lo que las ventajas de HATEOAS no destacan tanto
  • También hay barreras prácticas importantes, como la carga inicial de aprender los principios de REST y la complejidad de analizar enlaces dinámicos

Conclusión

  • Según las reglas de Fielding, una API verdaderamente RESTful requiere navegación dinámica basada en hipermedia (HATEOAS)
  • REST no consiste simplemente en implementar CRUD sobre HTTP, sino en una arquitectura enfocada en el acoplamiento débil, la capacidad de evolución y las transiciones dinámicas de estado, al igual que los principios de la web
  • En la práctica, puede ser más importante diseñar según la realidad del equipo y la utilidad concreta
    • Si se trata de una API pública para desarrolladores externos, se recomienda adoptar HATEOAS; si es una API solo para uso interno, un estilo RPC simple también puede ser práctico
  • La clave es diseñar una API que sea fácil de aprender y difícil de usar incorrectamente, y no necesariamente que sea RESTful

1 comentarios

 
GN⁺ 2025-07-10
Opiniones en Hacker News
  • Me identifico con el excesivo purismo que aparece aquí y también leí con interés el paper de Fielding, pero siento que esta ya es una guerra terminada. En cuanto escuchas el término API REST, casi puedes asumir lo siguiente:

    • La API devuelve JSON
    • Las operaciones CRUD están mapeadas a POST/GET/PUT/DELETE
    • El equipo debate interminablemente sobre los códigos de estado HTTP adecuados, y algunos códigos se usan distinto a como dice la especificación
    • También es posible que el endpoint de listado termine cambiándose a POST para soportar filtros complejos Como pasó con Agile, CI o DevOps, uno puede aferrarse a la definición original, o aceptar que el significado social ya cambió y usar el término con el sentido comúnmente entendido
    • Creo que la razón por la que Fielding “ganó” es precisamente que su lógica era contradictoria y en gran parte errónea. Es el paradigma de "worse is better" del siglo XXI. Los sistemas RPC tenían mala usabilidad y no tuvieron éxito, como Sun RPC, RMI, DCOM, CORBA, XML-RPC, SOAP y Protocol Buffers. La gente dice que REST no es RPC, pero en la práctica en Javascript haces una función como
    const getItem = async (itemId) => { ... }
    

    y esa función llama a

    GET /item/{item_id}
    

    En el backend hay una función como

    Item getItem(String itemId) { ... }
    

    y una anotación describe el mapeo de URL. Al final esto es RPC. Solo que, en vez de un sistema complejo y poco intuitivo, quedó en una forma más artesanal y bajo control del desarrollador. El 80% de la mayoría de los problemas viene de que la gente no usa el formato de fecha ISO 8601

    • No termino de entender por qué alguien vería esto como una “batalla” y le daría tanta importancia. El concepto de REST es útil, pero la parte de HATEOAS casi no tiene utilidad práctica y solo genera problemas. Si ves el Richardson maturity model, la cima de REST incluye elementos como HATEOAS. Tampoco entiendo la lógica de decir que si a REST le quitas HATEOAS entonces ya no es REST, porque no es una diferencia tan importante. Si HATEOAS es en la práctica casi insignificante, obsesionarse con esa clasificación purista parece no tener sentido. Richardson maturity model

    • En la parte de “el equipo discute demasiado sobre los códigos de estado y a menudo los usa distinto a la spec”, quiero recalcar que 401 Unauthorized debe usarse cuando no hay autenticación, y 403 Forbidden cuando no hay permisos

    • Yo suelo preguntarles a las personas si realmente van a usar el significado de REST definido en el paper. Normalmente soy de los que no toleran el abuso de términos vacíos. Al final digo “ah, entonces solo te refieres a una web API” y sigo adelante. La diferencia importante es que hay que identificar qué rarezas tiene cada una de esas APIs

    • Para mí el matiz realmente importante es que los “hipermedia links” parecen ser algo “general” mediante distintos link types (incluidos en headers HTTP o en el resultado devuelto), pero en la práctica el REST actual funciona igual. Por ejemplo, si por un mal diseño “activate” debía haber sido “enable”, al final igual tendrías que cambiar de /api/v1/account/ID/activate a /api/v2/account/ID/enable. Es decir, en algún lado tienes que hardcodear el significado de todas las acciones de la API (y además faltan metadatos extra como íconos, traducción de descripciones de acciones, etc.). La “generalidad” de este enfoque en realidad es una ilusión

  • Cuando hace 13 años me tocó desarrollar por primera vez una HTTP API, leí de principio a fin el paper de Fielding para entender qué era el REST real, y también leí RESTful Web Services Cookbook. Luego hice una API REST evitando las convenciones de Django. Fue una especie de enfoque de “cargo cult”, porque realmente no entendía qué ventajas le daba el verdadero REST a nuestro servicio. Solo después de varios años más creando distintas HTTP API terminé sintiendo que, en un contexto práctico, el purismo REST no aportaba beneficios. La visión de “self-discovery” y “compatibilidad con clientes genéricos” es casi imposible de materializar, y en concreto el paper de Fielding ni siquiera guía perfectamente sobre esos puntos. Para hacer una API realmente self-discoverable necesitas reglas concretas como “protocolos de descubrimiento de endpoints”, “descripción de operaciones”, “mensajes de ayuda”, etc. Y al final tienes que construir un cliente dedicado que entienda esas reglas, con lo cual se pierde la ventaja de un cliente generalizado. Es decir, en la realidad no quedó más que hacer código específico por servidor: API, JS, CLI, etc. Y además un buen UX choca con el ideal de REST, porque para lograr una experiencia realmente buena tienes que hacer código especializado en el frontend para la app. Los elementos UI también podrían estandarizarse, pero en la práctica es más útil construir una UI flexible con un lenguaje como JavaScript

    • Coincido con los límites del concepto de API self-discoverable. Un cliente REST real es prácticamente imposible de implementar. Necesitas saber cómo se comporta cada URL, y si aparece una acción nueva (por ejemplo, /cansofspam/123/frobnicate), el cliente no puede manejarla claramente. Al final necesitas actualizar el cliente, ignorarla, o como mucho agregar un botón muy simple (por ejemplo, Frobnicate). Por eso no existen servidores ni clientes REST en el sentido pleno del término. En la práctica funciona que el cliente soporte solo la API que espera, sin discovery

    • Las API tienen muchos aspectos, así que describirlas es difícil. Los usuarios de una API también necesitan saber cosas como la latencia promedio de respuesta, los códigos de error reintentables, la atomicidad/idempotencia de las acciones, etc. HATEOAS no basta para comunicar esas cosas. No hace falta implementar REST perfecto, y en el fondo la ventaja principal de REST es simplemente que existe un lenguaje uniforme para mapear sustantivos/verbos a métodos HTTP y URL. Aun así, hay una enorme cantidad de detalle y diseño fino. Por ejemplo, hay cosas que la spec HTTP permite pero que en un LB real no puedes usar, o decisiones sobre cuándo reintentar errores 500 y qué lógica de backoff aplicar

    • El navegador es justamente el “código genérico” y ofrece el mejor UX que usamos todos los días. El concepto de REST también incluye que el servidor pueda entregar código al cliente (aunque haya temas de seguridad, el navegador y los estándares han resuelto bastante de eso). Enlace a la sección relevante del paper de Fielding

    • La verdad es que incluso en una versión debilitada de la definición de REST tampoco hay mucha ganancia. Eso de “debes usar DELETE para borrar un recurso” no es tan importante. Si usas POST, ¿a quién le complica realmente?

    • Nunca pensé que “self-discoverable” fuera la meta, ni me parece algo alcanzable. En el diseño de clientes simples esa expectativa ya es demasiado alta desde el inicio. En especial porque ni siquiera en el TFA aparece la palabra ‘discoverable’

  • Donde este estilo de diseño de API sí es realmente útil es cuando el usuario y un agente que navega por él en su nombre (por ejemplo, un navegador) pueden recorrer la API e interactuar según el tipo de media y la información de enlaces en cada respuesta. La mayoría de las web APIs no están hechas para ese caso de uso, sino para webapps que buscan una UI/UX específica. Esa es una dirección elegida deliberadamente. Quien construye la app quiere controlar por completo la representación de los datos, el flujo de UI, etc., para cumplir los objetivos de la app. El diseño de una API REST se vuelve necesario cuando quieres que el usuario tenga más control directo sobre cómo se usan los recursos de la API. Por ejemplo:

    • Portales gubernamentales de información pública accesibles para cualquiera (leyes, clima, registros inmobiliarios, etc.)
    • Portales gubernamentales donde hay que enviar distintos formularios
    • Proyectos de datos abiertos como Wikipedia u OpenStreetMap Esas son áreas donde sí conviene adoptar diseño de API REST. Al final, quienes insisten estrictamente en la definición de REST suelen tener una formación más académica, mientras que quienes usan el término de forma amplia suelen ser desarrolladores enfocados en la experiencia de la app. La solución es simple: si no es REST de verdad, no lo llames REST
    • En realidad, un documento HTML es exactamente ese caso. Dentro del documento hay enlaces a otros documentos, y el usuario puede navegar a donde quiera según el texto del enlace. Si es para una persona lo llamamos UI, y si es para una aplicación lo llamamos API. HATEOAS se siente fuera de lugar porque parece como si quisieras adaptar la API directamente al usuario, pero eso ya lo disfrutamos en forma de UI

    • El concepto puro de REST es muy académico. En proyectos abiertos o de big data, para implementar rendimiento real o arquitectura real importa más un enfoque pragmático que cumplir o no con REST. Incluso los académicos al final tienen que construir algo, así que tampoco se aferran al REST perfecto

    • Este tipo de diseño de API es útil no solo para páginas web, sino también al construir otros clientes. Puedes obtener recursos con GET, extraer valores por campos/rutas y construir nuevos URI para operar, y con ese patrón se pueden armar muchas apps/CLI/UI. Si no es un SPA, incluso se puede implementar directamente con HTML; al final el usuario (o user-agent) hace dereference de la información dentro de la representación devuelta

    • Me pregunto si, en una era donde la IA consume APIs, este caso de uso se volverá más importante. La discoverability de una API favorece mucho más a una IA que a un desarrollador de webapps. Si ves MCP (protocolo de control inmersivo), puedes notar lo poderosa que es la tool discoverability. HATEOAS podría aportar una gran ventaja potencial también en el consumo de APIs bare

    • La documentación de la API RESTful del Servicio Meteorológico Nacional de EE. UU. es realmente agradable cuando una API de información pública está bien diseñada

  • Sobre la idea de que “la carga cognitiva inicial de construir un cliente realmente hipermedia-driven era enorme, y se sentía más cómodo simplemente hardcodear URI templates (/users/{id}/orders, etc.)”, también lo siento así por experiencia: de verdad es más fácil. Los principios REST puros ofrecen poca relación costo-beneficio en la mayoría de los casos. Es como si en un microondas un solo botón controlara el menú, el modo de funcionamiento y el tiempo, en vez de tener botones estándar que uno ya sabe usar: resulta mucho más engorroso. Incluso el lector de código del motor de 2 botones que uso en la vida real tiene una operación absurdamente incómoda. La cultura de decir que todavía “hay que leer obligatoriamente el paper de Fielding” sigue siendo bastante polémica. Si una idea es buena, debería poder explicarse fácilmente de muchas formas y desde una perspectiva popular. Por ejemplo, nadie dice que para entender física hay que leer obligatoriamente los Principia de Newton

  • Para que valga la pena adoptar patrones RESTful/HATEOAS de verdad, necesitas clientes que los entiendan. htmx: hypermedia clients intercoolerjs: hatoeas-is-for-humans

  • Los diseñadores de UI quieren controlar el look detallado de la pantalla. Algunas acciones posibles sobre un recurso querrán mostrarlas como botones grandes, otras esconderlas en un menú o ni siquiera mostrarlas en la UI. Si las acciones se renderizan dinámicamente según la respuesta de la API para cada estado concreto, todas terminan viéndose iguales. Por eso creo que una API RESTful no es apropiada para implementar la UI habitual de un frontend web

    • Hay varios errores en esa afirmación

      1. Los diseñadores UX participan en todo el ciclo de desarrollo del producto y no necesariamente tienen control absoluto. La ubicación de una acción concreta dentro de la UI es distinta del “state” de la acción. Es decir, si el estado impone restricciones, la UX debe seguir esas restricciones
      2. Arquitectónicamente, si encapsulas la verificación de estado, muchas veces if (resource.links['action'] !== null) es mucho mejor que if (state === something). La mayoría de los cambios de state requieren validación del servidor, y si eso se implementa solo del lado del servidor, también baja la complejidad del frontend. He desarrollado apps HATEOAS durante bastante tiempo y también mantengo HAL4J. Hay complejidad, pero el diseño UI en sí no es la barrera de entrada
    • En mi experiencia, desarrollar una “RESTful API” no solía estar directamente relacionado con la UI. Si de verdad solo necesitas UI, la API en sí es innecesaria; basta con hacerlo de manera server-driven (como el antiguo DWR, etc.)

  • Parece que HATEOAS casi no se usa en la práctica, así que no entiendo muy bien por qué sigue discutiéndose tanto. Me pregunto si realmente hay lugares que lo usen, y qué tipo de “cliente de navegación automática” puede funcionar sin conocer de antemano la información del servidor

    • Vale la pena recordar que ACME (el protocolo de Let’s Encrypt) está basado en HATEOAS. Eso se usa, en la práctica, en la mayoría de los servicios HTTPS. El propio HTTP, si se usa correctamente, también es un protocolo HATEOAS. El “auto-discovery” consiste en poder navegar recursos mediante tipos de enlace o cosas como ‘next’. Eso sí, el cliente igual debe conocer de antemano el significado de “next”. Los LLM también son buenos en este tipo de navegación automática

    • Usé HATEOAS en un sistema empresarial de videovigilancia, y resolvía muy bien problemas de versiones y permisos a nivel de API. También usamos varios RFC en conjunto. Pero el problema número uno era que la gente buscaba “conveniencia” de maneras que rompían el modelo y al final generaban más complejidad. Además, JSON no es por naturaleza un formato de hipertexto, así que intentar meter HATEOAS a la fuerza dentro de application/json se sentía forzado

    • Estoy usando HATEOAS para escribir un comentario, y justo ahora también estoy publicando una respuesta. El “cliente mágico de navegación automática” que procesa esto es el “navegador web”

    • htmx quizá sea el intento más realista

    • Ni siquiera estándares como OData se usan mucho, y tampoco son especialmente populares. HATEOAS tiene todavía menos popularidad y menos estandarización, así que parece todavía menos probable que se expanda

  • Algo que siempre se pasa por alto en esta discusión es el tipo de consumidor de la backend API. REST y HATEOAS suelen tener más sentido cuando quien consume la API es un tercero que no posee directamente el backend. Por ejemplo, en una página HTML tradicional, el consumidor final es el usuario del navegador. El MCP reciente también surgió para casos donde hace falta “descubrir e interpretar” múltiples APIs JSON RPC. En cambio, cuando frontend y backend están acoplados 1:1, el beneficio de REST no suele justificar el costo. Hay que documentar/especificar de manera más genérica, y en la práctica a veces son más útiles herramientas que ignoran la separación de concerns y priorizan la productividad (como trPC). En etapa de prototipo, la integración end-to-end es rápida

  • Respecto a la afirmación de que con HATEOAS y schema reference (XSD, JSON Schema, etc.) se pueden hacer clientes de navegación dinámica, en la práctica funciones de JSON Schema como "additionalProperties" terminan repitiendo el problema desde su origen. Me parece más sólido entregar la documentación “out of band”. Entonces, ¿qué pasaría si en "_links" solo se ofreciera un enlace al documento Swagger, y el cliente procesara esa información self path? Si fuera así, ¿para qué tendría que existir "_links"? Si ya existe un cliente capaz de manejar documentos JSON tan complejos, entonces con plantillas de Swagger u otras herramientas tendrías mucha más densidad de información y dinamismo. Solo con enlaces CRUD no basta para describir bien toda una API, y tampoco es posible cubrirlo todo con JSON Schema

  • Si simplemente lo llamamos HTTP API, todos salen ganando. REST nunca fue diseñado originalmente para APIs. Desde el principio, REST estaba pensado para sistemas de información consumidos por personas, no por programas