una - ventajas api rest
¿En qué parte de la arquitectura de HATEOAS especifica los verbos HTTP? (4)
¿Sabe si debe PONER o POSTAR a / account / 12345 / close?
Consulta la documentación de la API, así es como sabes. HATEOS no es un reemplazo para la documentación formal. La documentación es necesaria para las API REST al igual que cualquier otra API.
HATEOS le permite saber cuáles son sus otras opciones de un recurso específico. No le dice por qué usaría esas opciones ni qué información le enviaría. Los tipos de contenido solo expresan la sintaxis y la semántica de alto nivel, no la semántica de nivel de aplicación, por lo que tampoco son documentación.
Si desea saber cómo usar una API REST, lea la documentación. Si desea que otra persona utilice su API REST, proporcióneles la documentación.
No hay magia aquí.
Estaba leyendo un article en HATEOAS y si bien comprendo la idea de proporcionar las URL para otras acciones en la respuesta, no veo dónde se especifica qué verbos HTTP deberían usarse para interactuar con esas URL.
Por ejemplo, de ¿Qué es HATEOAS y por qué es importante para mi API REST? , como de esta respuesta
GET /account/12345 HTTP/1.1
HTTP/1.1 200 OK
<?xml version="1.0"?>
<account>
<account_number>12345</account_number>
<balance currency="usd">100.00</balance>
<link rel="deposit" href="/account/12345/deposit" />
<link rel="withdraw" href="/account/12345/withdraw" />
<link rel="transfer" href="/account/12345/transfer" />
<link rel="close" href="/account/12345/close" />
</account
¿Sabe si debo emitir un HTTP PUT
o POST
a /account/12345/close
?
La respuesta de @Cormac Mulhall es muy buena, pero me gustaría sugerir un refinamiento que escuché de un colega:
Las acciones o eventos que suceden a un recurso pueden tratarse como nombres de dominio subordinados, usando la forma gerund del verbo de acción o el nombre del evento, pero deben colocarse bajo un identificador de ruta significativo como "acciones" o "eventos" o algo similar . La representación de recursos que se devolverá expresa datos de estado sobre la acción, de modo que POST
o PUT
funcionan como una solicitud.
Supongamos que las órdenes tienen varios estados de ciclo de vida. En algún momento después de redactarse, un pedido se realiza, se realiza o se cancela.
La información sobre estas acciones de orden se ubicaría al poner el nombre de la acción en forma de sustantivo plural debajo de la ruta de recursos con /actions
para devolver detalles si el estado de las acciones está activo, o 404 NOT FOUND
contrario.
https://order.api.foobar.com/v1.0/orders/{orderId}/actions/placements
https://order.api.foobar.com/v1.0/orders/{orderId}/actions/fulfillments
https://order.api.foobar.com/v1.0/orders/{orderId}/actions/cancellations
Cuando estas acciones son idempotentes (una orden no se puede colocar dos veces seguidas), por lo tanto, estas acciones se pueden solicitar mediante la PUT
de la representación apropiada para estos URI. Cuando no son idempotentes, se crean mediante POST
''a la forma plural.
Por ejemplo, para realizar un seguimiento del pedido de aprobaciones, podríamos POST
:
https://order.api.foobar.com/v1.0/orders/{orderId}/approvals
y luego vemos información sobre aprobaciones individuales al hacer un GET contra:
https://order.api.foobar.com/v1.0/orders/{orderId}/approval/1
A menudo es útil usar un agregado llamado algo como "acciones" para encontrar todas las acciones:
https://order.api.foobar.com/v1.0/orders/{orderId}/actions
Podríamos hacer POST
a esto, dejando que la representación declare qué tipo de acción significa.
También puede obtener una lista de acciones a través de órdenes individuales dejando el parámetro {orderId}
desactivado:
https://order.api.foobar.com/v1.0/orders/actions/placements
https://order.api.foobar.com/v1.0/orders/actions
Se pueden buscar agregando parámetros de consulta:
https://order.api.foobar.com/v1.0/orders/actions/placements?since={sinceTimestamp}
No ponga verbos en sus URI (por ejemplo, / account / 12345 / transfer ). Los URI representan recursos, no acciones.
Los verbos a usar están definidos por el protocolo HTTP (por ejemplo, GET
, POST
, PUT
, OPTIONS
, DELETE
, etc.). REST es un diseño de arquitectura con un conjunto de restricciones, y HTTP es un protocolo que se adhiere a estas restricciones. HTTP define un conjunto limitado de verbos para transferir el estado de un recurso del cliente al servidor y viceversa. Por definición, estás limitado a estos verbos solamente.
El cliente debe decidir qué verbo HTTP usar en función de lo que está tratando de hacer. El servidor no necesita decirle qué verbos hay, ya lo sabe basándose en el protocolo HTTP.
Si el cliente necesita saber qué verbos puede usar en un recurso, puede consultar el recurso usando el verbo OPCIONES y ver el encabezado Allow
en la respuesta (asumiendo que el servidor devuelve esta información, lo cual debería ser útil). Algunos recursos solo pueden aceptar GET, mientras que otros pueden aceptar otros como POST y PUT.
Eche un vistazo a la especificación HTTP para ver qué verbo usar en qué contexto.
Para dar un ejemplo de su publicación original. Digamos que tienes un recurso de cuenta con un URI en
/accounts/12345
y quieres cerrar la cuenta. Recuerde que REST es transferencia de estado . El cliente está cerrando la cuenta por lo que tiene la cuenta en un estado de cerrado al final. Luego transfiere ese estado al servidor para que tanto el cliente como el servidor estén alineados entre sí. Así que PUT
el estado de los clientes (que es el recurso en un estado cerrado) en el servidor
PUT /accounts/12345
El cuerpo de la solicitud debe contener una representación del recurso en un estado cerrado. Suponiendo que está utilizando XML para representar el recurso de la cuenta, sería algo como esto
PUT /accounts/12345
<?xml version="1.0"?>
<account>
<account_number>12345</account_number>
<balance currency="usd">100.00</balance>
<state>closed</state>
</account>
El recurso en el servidor ahora refleja el recurso en el cliente. Ambos están en un estado cerrado. Si no desea transferir todo el recurso cada vez que realiza un cambio en uno de sus atributos, puede dividirlos en una jerarquía de recursos. Haga que el estado de la cuenta sea su propio recurso y PUEDE cambiarlo.
PUT /accounts/12345/status
<?xml version="1.0"?>
<state>closed</state>
Su pregunta tiene muchas respuestas en Stackoverlow, pero la mayoría de ellas elude el motivo por el que la pregunta, y sospecho que siempre las encuentra parcialmente insatisfactorias.
Si le tomamos la palabra a Roy Fielding, es imposible escribir la mayoría de las aplicaciones comerciales interactivas del Cliente como SOA RESTful / HATEOAS utilizando HTTP / HTML. Podría ser posible en otros medios, no puedo decir.
Por lo tanto, la respuesta práctica es " búsquelo en la documentación " y " escriba a su Cliente con el conocimiento de la aplicación " con un lado de " ignorar el hecho de que estamos rompiendo las reglas de Fielding al hacer eso ".
Tiendo a diseñar respuestas JSON que proporcionan este enfoque:
GET /account/12345 HTTP/1.1
{
"account": {
"number": "12345",
"currency": "usd",
"balance": "100.00",
"deposit": {
"href": "/account/12345/deposit",
"action": "POST"
},
"withdraw": {
"href": "/account/12345/withdraw",
"action": "POST"
},
"transfer": {
"href": "/account/12345/transfer",
"action": "POST"
},
"close": {
"href": "/account/12345/close",
"action": "DELETE"
}
}
}
... agregando propiedades adicionales al diseño según sea necesario, pero estos son los conceptos básicos.
Creo que esto permite que los clientes consumidores se escriban de forma RESTABLE, pero al hacerlo, estoy usando el Cuerpo de Respuesta, que Fielding dice que no es lo que pretendía.
Sin embargo, ofrecería esta explicación por separado a la respuesta:
Fielding dice: "Me siento frustrado por la cantidad de personas que llaman a cualquier interfaz basada en HTTP una API REST". ( http://roy.gbiv.com/untangled/2008/rest-apis-must-be-hypertext-driven ).
Tenga en cuenta cómo dice de manera tan estridente " cualquier " interfaz basada en HTTP.
El segmento más relevante en su ''conferencia'' es este:
" 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 sean apropiados para la audiencia prevista (es decir, se espera que sea entendido por cualquier cliente que pueda usar la API). punto, todas las transiciones de estado de la aplicación deben ser dirigidas por la selección del cliente de las opciones provistas por el servidor que están presentes en las representaciones recibidas o implícitas en la manipulación de esas representaciones por parte del usuario. Las transiciones pueden ser determinadas (o limitadas por) el conocimiento del cliente sobre los medios tipos y mecanismos de comunicación de recursos, los cuales pueden mejorarse sobre la marcha (por ejemplo, código a pedido). [La falla aquí implica que la información fuera de banda está impulsando la interacción en lugar del hipertexto.] "
Dice esto porque un tipo de medio URI de aplicación HTTP / HTML es solo "texto / html", y ¿dónde está el Verbo en eso? No hay uno Un URI no puede decirle qué Verbo requiere algo para su uso / navegación, por lo que no puede usar solo los datos dentro de la banda solo para construir la "próxima" navegación de forma dinámica en su Cliente.
Explicó que cree que representamos nuestro URI como parte de CDATA que incluye el "método" o que el contexto del URI lo proporcionaría de manera evidente, como lo hace el elemento FORM. Explica explícitamente contra la API REST de OpenSocialst que indica que no es REST.
Aquí: “los elementos de anclaje con un atributo href crean un enlace de hipertexto que, cuando se selecciona, invoca una solicitud de recuperación (GET) en el URI correspondiente al atributo href codificado en CDATA”. Los identificadores, los métodos y los tipos de medios son preocupaciones ortogonales: métodos No se les da significado por el tipo de medio. En su lugar, el tipo de medio le dice al cliente qué método usar (por ejemplo, ancla implica GET) o cómo determinar el método a usar (por ejemplo, el elemento de formulario dice buscar en el atributo del método). El cliente ya debe saber qué significan los métodos (son universales) y cómo desreferenciar un URI .
Tenga en cuenta que dice que el Cliente ya debería saber qué significan los métodos, que no dice que el Cliente ya debería saber qué son , por lo que hizo su pregunta. Mucha gente lucha con esto, porque de hecho no construimos nuestras aplicaciones como esta en la mayoría de los entornos SOA.
Como muchos ingenieros, solo deseo que Fielding salga con una aclaración o una nueva declaración, pero no solo no lo ha hecho, sino que ha publicado dos advertencias adicionales para nosotros como ingenieros, que han duplicado su declaración y han dicho que deberíamos dejar de llamar a REST de nuestra API y aceptar que estamos construyendo RPC.
Creo que el enfoque tipo elementos de JSON es un puente sólido, pero no tengo respuesta al hecho de que estamos usando el Cuerpo de Solicitudes para hacerlo, no confiando en el Tipo de Medios para implicarlo.
Finalmente, hay un verbo más nuevo en HTTP llamado OPCIONES que, para un URI dado, devolvería la lista de acciones del verbo permitidas. Creo que Fielding tuvo una mano en escribir esta revisión HTTP. Eso permitiría a un Cliente construir genéricamente navegaciones URI sin el conocimiento interno prohibido de la aplicación. Pero eso tiene tres problemas en los que puedo pensar en el mundo práctico:
- Tendría que codificar un mecanismo en su Agregación de Servicios para hacer esa llamada para cada URI que intente devolver, y dado que muchos datos contienen muchos URI (_links en HAL) que agregan muchos ''saltos'' adicionales en su construcción de Respuesta de Servicio. Probablemente todos nos quejaríamos de eso.
- Prácticamente ningún sitio de SOA que dice ser RESTful implementa realmente una llamada de método-verbo OPCIONES para que usted haga esta consulta de todos modos.
- Todos nos quejaríamos por las llamadas adicionales "innecesarias" que agrega (especialmente en el mundo del comercio electrónico) al procesamiento de un Cliente y su tendencia a llevarnos más allá de los requisitos de SLA.