¿Esa API REST es realmente RPC? Roy Fielding parece pensar que sí

99

Una gran cantidad de lo que pensé que sabía sobre REST aparentemente está mal, y no estoy solo. Esta pregunta tiene una larga introducción, pero parece necesaria porque la información está un poco dispersa. La pregunta real viene al final si ya está familiarizado con este tema.

Desde el primer párrafo de las API REST de Roy Fielding deben estar impulsadas por hipertexto , está bastante claro que él cree que su trabajo está siendo ampliamente malinterpretado:

Me frustra la cantidad de personas que llaman a cualquier interfaz basada en HTTP una API REST. El ejemplo de hoy es la API REST de SocialSite . Eso es RPC. Grita RPC. Hay tanto acoplamiento en exhibición que debería recibir una calificación X.

Fielding continúa enumerando varios atributos de una API REST. Algunos de ellos parecen ir en contra de la práctica común y los consejos comunes en SO y otros foros. Por ejemplo:

  • Se debe ingresar una API REST sin conocimiento previo más allá del URI inicial (marcador) y un conjunto de tipos de medios estandarizados que son apropiados para la audiencia prevista (es decir, se espera que los comprenda cualquier cliente que pueda usar la API). ...

  • Una API REST no debe definir jerarquías o nombres de recursos fijos (un acoplamiento obvio de cliente y servidor). ...

  • Una API REST debería dedicar casi todo su esfuerzo descriptivo a definir los tipos de medios utilizados para representar recursos y controlar el estado de la aplicación, o definir nombres de relaciones extendidas y / o marcas habilitadas para hipertexto para tipos de medios estándar existentes. ...

La idea de "hipertexto" juega un papel central, mucho más que la estructura URI o lo que significan los verbos HTTP. "Hipertexto" se define en uno de los comentarios:

Cuando yo [Fielding] digo hipertexto, me refiero a la presentación simultánea de información y controles de manera que la información se convierte en la posibilidad a través de la cual el usuario (o autómata) obtiene opciones y selecciona acciones. Hypermedia es solo una expansión de lo que significa el texto para incluir anclajes temporales dentro de un flujo de medios; la mayoría de los investigadores han abandonado la distinción.

El hipertexto no necesita ser HTML en un navegador. Las máquinas pueden seguir enlaces cuando comprenden el formato de datos y los tipos de relaciones.

Supongo que en este punto, pero los dos primeros puntos anteriores parecen sugerir que la documentación de API para un recurso de Foo que se parece a lo siguiente conduce a un acoplamiento estrecho entre el cliente y el servidor y no tiene lugar en un sistema RESTful.

GET   /foos/{id}  # read a Foo
POST  /foos/{id}  # create a Foo
PUT   /foos/{id}  # update a Foo

En cambio, un agente debería verse obligado a descubrir los URI de todos los Foos, por ejemplo, emitiendo una solicitud GET contra / foos. (Esos URI pueden seguir el patrón anterior, pero eso no viene al caso). La respuesta utiliza un tipo de medio que es capaz de transmitir cómo acceder a cada elemento y qué se puede hacer con él, dando lugar al tercer punto anterior. . Por este motivo, la documentación de la API debe centrarse en explicar cómo interpretar el hipertexto contenido en la respuesta.

Además, cada vez que se solicita un URI a un recurso de Foo, la respuesta contiene toda la información necesaria para que un agente descubra cómo proceder, por ejemplo, accediendo a los recursos asociados y principales a través de sus URI, o tomando medidas después de la creación. / eliminación de un recurso.

La clave de todo el sistema es que la respuesta consiste en hipertexto contenido en un tipo de medio que transmite a sí mismo al agente opciones para continuar. No es diferente a la forma en que funciona un navegador para los humanos.

Pero esta es mi mejor suposición en este momento en particular.

Fielding publicó un seguimiento en el que respondió a las críticas de que su discusión era demasiado abstracta, carente de ejemplos y rica en jerga:

Otros intentarán descifrar lo que he escrito de maneras que sean más directas o aplicables a alguna preocupación práctica de hoy. Probablemente no lo haga, porque estoy demasiado ocupado lidiando con el próximo tema, preparándome para una conferencia, escribiendo otro estándar, viajando a algún lugar distante o simplemente haciendo las pequeñas cosas que me hacen sentir que me he ganado mi sueldo.

Entonces, dos preguntas simples para los expertos en REST con una mentalidad práctica: ¿cómo interpretas lo que dice Fielding y cómo lo pones en práctica al documentar / implementar API REST?

Editar: esta pregunta es un ejemplo de lo difícil que puede ser aprender algo si no tienes un nombre para lo que estás hablando. El nombre en este caso es "Hypermedia como motor del estado de la aplicación" (HATEOAS).

Rico Apodaca
fuente
26
John, Rich solo está explicando el cambio de mentalidad que tuvo. No hay nada subjetivo o argumentativo al respecto. Vote para mantenerse abierto: es una de las mejores preguntas etiquetadas como "descanso" que he visto en SO.
Keith Gaughan
4
Keith, "explicar el cambio de mentalidad" es algo que debería hacer en su blog, no en SO.
John Saunders
13
No está explicando su cambio de mentalidad, está preguntando si su comprensión es correcta.
aehlke
4
Excelente resumen. Aprendí más de esta pregunta que de la mayoría de las respuestas.
Martin Konecny

Respuestas:

21

Creo que tu explicación lo cubre principalmente. Los URI son identificadores opacos que, en su mayor parte, no deben comunicarse más allá del URI de marcador que utiliza el agente de usuario para acceder a la aplicación.

En cuanto a la documentación, esta pregunta se ha hecho varias veces. Documenta su tipo de medio, junto con los controles de hipervínculo que contiene (enlaces y formularios), y el modelo de interacción si así lo desea (ver AtomPub).

Si documenta los URI o cómo crearlos, lo está haciendo mal.

SerialSeb
fuente
¿Sigue siendo cierto esto? Hay especificaciones de respuesta de API como Ionspec que han creado estos URI como parte de la respuesta de forma intencionada.
Sean Pianka
Sí, tienen. En ese punto, es cuestión de averiguar si esos URI documentados son solo puntos de entrada a la aplicación, que están garantizados para permanecer (algunos de ellos no son infrecuentes y bastante útiles) o si, debido a que la gente quiere la generación de código, esos están incrustados desde una especificación directamente en el código, evitando que el servidor le permita al cliente saber cómo puede hacer las cosas. Si el cliente cree que lo sabe debido a ese contrato, no estás en hipermedia, estás en el modelo moderno de jabón openapi, con los mismos problemas que habrías encontrado con eso hace 18 años.
SerialSeb
Lo que es cierto es que muchos lenguajes de documentación de API se han desarrollado en los últimos 11 años, pero los fundamentos no han cambiado. Creo que el valor de descubrir esos enlaces, o al menos el descubrimiento de plantillas de URI, está en la construcción de un código de cliente genérico reutilizable que pueda usarlos dinámicamente, permitiendo que muchas implementaciones en el lado del servidor reutilicen el mismo código de cliente. La incrustación de URI continúa dificultando estos escenarios, pero si usa esos formatos, tiende a acoplar estrechamente un cliente generado a partir de esas especificaciones, por lo que ya ha perdido esa característica.
SerialSeb
8

Tu interpretación me parece correcta. Creo que las limitaciones de Fielding se pueden aplicar de forma práctica.

Realmente me gustaría ver a alguien publicar algunos buenos ejemplos de cómo documentar una interfaz REST. Hay tantos ejemplos deficientes, tener algunos válidos para señalar a los usuarios sería muy valioso.

Darrel Miller
fuente
2
Guau. Esa página del Modelo de recursos me hizo llorar. Esperemos que esto inicie una tendencia.
Darrel Miller
Es una pena que este sea básicamente el único ejemplo de una API de este tipo en la web. Peor aún, no hay buenos ejemplos de código de cliente que siga el principio en absoluto (que he encontrado).
jkp
1
@DarrelMiller ¿Pero esos tipos de medios no son demasiado "específicos"? Me parece que su API realmente usa solo un MIME: application/jsony que el modelo de recursos son realmente las relaciones. ¿Entendí mal este aspecto de REST? También he leído una de sus respuestas SO que parece señalar que esos contratos de "un atributo" deben evitarse ...
edsioufi
2
@RichApodaca Tu enlace ha muerto de disentería. web.archive.org/web/20170409132237/https://kenai.com/projects/…
forresthopkinsa
5

He estado buscando un buen ejemplo de una API escrita siguiendo las HATEOAS y tuve problemas para encontrar una (encontré que tanto la API de SunCloud como AtomPub eran difíciles de aplicar a una situación de API "normal"). Así que intenté hacer un ejemplo realista en mi blog que siguiera los consejos de Roy Fieldings sobre lo que significa ser una implementación REST adecuada. Me resultó muy difícil dar con el ejemplo, a pesar de que, en principio, es bastante simple (simplemente confuso cuando se trabaja con una API en lugar de una página web). Entiendo con lo que Roy estaba teniendo problemas y estoy de acuerdo, es solo un cambio en la mentalidad para implementarlo correctamente para una API.

Eche un vistazo: Ejemplo de API usando Rest

Jeremyh
fuente
4

La única excepción a dar instrucciones sobre cómo construir URI es que está permitido enviar una plantilla de URI en la respuesta de hipertexto, con campos que el cliente debe sustituir automáticamente, utilizando otros campos en el hipertexto. Sin embargo, esto generalmente no termina ahorrando mucho ancho de banda, ya que la compresión gzip manejará las partes repetidas de los URI lo suficientemente bien como para no molestarse con esto.

Algunas buenas discusiones sobre REST y los HATEOAS relacionados:

Ventajas de (también) usar HATEOAS en API RESTFul

Cómo tomar una taza de café

aehlke
fuente
4

Para los interesados, encontré un ejemplo detallado de HATEOAS en la práctica en Sun Cloud API .

Rico Apodaca
fuente
2
Link está muerto. Archivo
sea
4

Lo que la mayoría de la gente se equivoca es que (al menos eso creo) en el mundo REST no documenta su "interfaz de descanso", lo que documenta es un tipo de medio, independientemente de su servidor o servicio.

redben
fuente
2

Creo que a lo largo de la cantidad de años que REST ha estado ahí, los tecnólogos han llegado a un acuerdo con el concepto de un recurso y lo que realmente es o no es REST.

De acuerdo con el Modelo de Madurez de Richardson, hay 4 niveles (0-3) que definen cuán RESTful es su API, con 3 significando una API RESTful, tal como Roy Fielding pretendía que fuera.

El nivel 0 es cuando tiene un URI de punto de entrada, como SOAP.

El nivel 1 significa que la API es capaz de distinguir entre diferentes recursos y tiene más de un punto de entrada; todavía huele a SOAP.

El nivel 2 es cuando usa verbos HTTP: GET, POST, DELETE principalmente. Este es el nivel en el que REST realmente entra en escena.

En el nivel 3, comienza a usar controles hipermedia para hacer que su API sea realmente RESTful.

Enlaces sugeridos para lectura adicional:

Sampada
fuente
1

Absolutamente correcto. Me gustaría señalar además que las plantillas de URI están perfectamente bien dentro de una aplicación RESTful siempre que los patrones sean de documentos recibidos del servidor (OpenSearch es un ejemplo adecuado). En el caso de las plantillas de URI, usted documenta dónde se utilizan y cuáles son los marcadores de posición esperados en la plantilla, pero no las plantillas en sí. Algo contrario a lo que dijo Wahnfrieden, esto no es una excepción.

Por ejemplo, en mi trabajo tenemos un sistema de administración de dominio interno y el documento de servicio especifica dos plantillas de URI: una para producir una URI de mejor estimación para un recurso de dominio y otra para construir una URI para consultar la disponibilidad del dominio. Todavía es posible hojear la colección de dominios para averiguar cuál es el URI de un dominio dado, pero dada la inmensa cantidad de dominios que administra, esto no sería factible para el cliente, por lo que les da una forma de adivinar cuál es el El URI de un recurso de dominio podría ser una gran ventaja en términos de facilidad de implementación desde la perspectiva del cliente y ancho de banda desde el servidor.

Continúe con su pregunta: nuestra documentación normativa son los recursos expuestos, el efecto de varios métodos en esos recursos y los tipos de medios de representación utilizados y sus esquemas, y a qué tipo de recursos apuntan las URI en esas representaciones.

También incluimos documentación no normativa (informativa) que ha adjuntado un descargo de responsabilidad para no leer demasiado en los URI mencionados en el documento, que brinda ejemplos de interacciones típicas cliente-servidor. Esto pone la documentación normativa bastante abstracta en términos concretos.

Keith Gaughan
fuente
1
Está bien proporcionar plantillas de URI como parte de su API, fuera de banda. Solo POR FAVOR NO se refiera a esto como DESCANSO, porque no lo es. Esa es una gran cantidad de acoplamiento, y exactamente lo que REST se hizo para evitar. Pero como dices, REST no es para todas las aplicaciones. Así que no pretenda que todas las aplicaciones son REST.
aehlke
1
De hecho, estoy de acuerdo. Creo que eso es lo que dije. Sin embargo, realmente no veo ninguna buena razón para proporcionar plantillas de URI fuera de banda.
Keith Gaughan
0

Supongamos que GET /foos/createFormse invoca para obtener valores de campos de formulario para los que se deben proporcionar cuando vayamos a crear POST /foos. Ahora, esta URL en particular, es decir, la 1 utilizada para crear foos, debe mencionarse en la respuesta GET /foos/createFormcomo un enlace de acción de envío de acuerdo con la propuesta de Fielding, ¿verdad?
Entonces, ¿cuál es el beneficio de mapear acciones a verbos Http conocidos a acciones? Se anula la "convención sobre código / configuración".

redzedi
fuente