RESTful
Un repaso al tutorial RESTful
Intro
- Construir RESTful web services (WS) es en parte arte y en parte ciencia.
- No hay un estándar para construir RESTful WS.
- Es importante construir RESTful WS de acuerdo a las buenas prácticas de la industria.
- Las buenas prácticas facilitan el desarrollo e incrementan la adopción por parte del cliente.
Qué es REST
Las siglas REST significan: REpresentational State Transfer
- Basado en recursos
- Representaciones
- Tiene seis restricciones:
- Interface uniforme
- Sin estado (Stateless)
- Cliente - Servidor
- Cacheable
- Sistema en capas
- Código bajo demanda
Interface Uniforme
- Define la interface entre los clientes y los servidores.
- Simplifica la arquitectura.
- Desacopla la arquitectura.
- Permite la evolución del sistema de manera independiente.
Interface Uniforme (cont...)
Interface uniforme tiene cuatro principios guía:
- Basado en recursos.
- Recursos manipulados a través representaciones.
- Mensajes autodescriptivos
- Hypermedia como el motor del estado de la aplicación(HATEOAS)
Stateless
El estado está dentro del request.
- Como parte de la URI (qué recurso).
- Como parámetros del query-string.
- En el body(estado deseado, nuevo, cambiado).
- En los encabezados(meta-información).
No hay sesion client -> server -> cliente
Potencia la escalabilidad. Cada petición es una nueva petición.
Stateless (cont...)
Manipulación de estado de un recurso:
- Server recibe request
- Server procesa request a estado apropiado
- Comunica el resultado al cliente vía los headers, el Http Status y el response body.
Cacheable
Los clientes pueden cachear respuestas.
Las respuestas deben definir de manera implicita o explicita si son cacheables o no, para reusar o no sus datos en futuras peticiones.
Bien manejado, este mecanismo elimina algunas interacciones entre cliente-servidor, mejora escalabilidad e incrementa el performance.
Cliente - Servidor
- Clientes y servidores separados.
- Los clientes no saben del detalle de implementación, almacenamiento y/o tecnología en el servidor y viceversa.
- La portabilidad aumenta.
- Código en servidor más simple y más escalable.
- Clientes y servidores reemplazables, siempre y cuando la interface no se altere.
Sistema en capas
- Los clientes no saben si hacen la petición sobre un recurso en un servidor en particular o a un servidor intermedio (API Manager).
- Los servidores intermedios mejoran la escalabilidad, el balanceo de carga, el monitoreo del flujo de peticiones y permiten agregar politicas de seguridad, entre otras ventajas.
Código bajo demanda (opcional)
El servidor puede transferir comportamiento (lógica) al cliente para que este último lo ejecute.
- Componentes compilados (Java applets)
- Client-side scripts (JavaScript)
Es la única restricción opcional. Es decir, un servicio web puede denominarse RESTful si cumple todas las restricciones o todas menos esta.
REST API
Consejos rápidos
Usar un verbo HTTP con significado
Los clientes de las APIs usan los verbos HTTP para las operaciones que representan:
- GET. Leer uno o una colección de recursos.
- PUT. Actualiza recurso por su identificador.
- DELETE. Elimina recurso por su identificador.
- POST. Crea nuevo recurso. Se usa para otras operaciones que no se corresponden con un verbo HTTP, por ejemplo, login, notify, etc.
La operación GET no debe cambiar el estado del recurso. Tras un GET el recurso sigue siendo el mismo.
Usar nombre de recurso sensibles
Construir un API es 80% arte y 20% ciencia.
La parte artística es crear una jerarquía URL que represente recursos sensibles.
Ejemplos:
/customer -> todos los clientes
/customer/123 -> cliente 123
/customer/123/orders -> ordenes de cliente 123
/customer/123/orders/45 -> orden 45 de cliente 123
/customer/123/orders/45/products -> productos en orden 45 de cliente 123
/customer/123/ordes/45/products/67 -> producto 67 de orden 45 de cliente 123
Usar nombre de recurso sensibles
Usa identificadores en la URL en lugar de en el query-string:
- Bien: /customers/123
- Nada bien: /api?tipo=customer&id=123
Nombra los recursos en su orden natural
Diseña para los clientes, no para tus datos
Nombres de recursos como sustantivos, no como verbos. La acción la define el HTTP Verb
Usar nombre de recurso sensibles
Utiliza plurales en los nombres de recursos
Si se trata de colecciones:
- Bien /customers
- Nada bien /customer_list
Utiliza lower-case en segmentos, separando palabras con "-"
- Bien /api/global-shop/monthly-promotions
- Nada bien /API/GlobalShop/monthlyPromotion
URIs cortas, tanto como sea posible, no restando significado
Usar HTTP Response Codes para indicar Status
Son un estándar.
Existe uno para casi todas las situaciones.
Usar los relevantes en cada situación.
Ejemplo:
Create resource -> 201 CREATED
Usar JSON en lugar de XML
JSON
{ "montoCredito": 200000.00, "comisionAnual": 1100, "tasaInteresAnual": 35, "pagoMinimo": 10 }
XML
<?xml version="1.0" encoding="UTF-8" ?>
<montoCredito>200000</montoCredito>
<comisionAnual>1100</comisionAnual>
<tasaInteresAnual>35</tasaInteresAnual>
<pagoMinimo>10</pagoMinimo>
Métodos HTTP en RESTful WS
Cada quien con su cada cual'
Acciones sobre los recursos
Los más usados:
- POST
- GET
- PUT
- DELETE
Se corresponden con las operaciones CRUD sobre los recursos.
Otros verbos no tan utilizados con REST
- PATCH
- HEAD
- OPTIONS
Correspondencia verbo HTTP, operación CRUD, Response code
| Verbo HTTP | Operación CRUD | Response Code |
|---|---|---|
| POST | Create | 201 Created, 404, 409 |
| GET | Read | 200 OK, 404 |
| PUT | Update/Replace | 200, 204, 404 |
| DELETE | Delete | 200, 404 |
POST
- Para crear nuevos recursos.
- En particular, para crear recursos subordinados (a un parent resource)
- Regresa un 201 en caso de éxito.
- No es seguro ni idempotente, es decir, dos request POST idénticas resultará en dos recursos con la misma información. La validación debe ser a mano.
Ejemplos POST:
- POST https://api.invexbt.com/customers
- POST https://api.invexbt.com/customers/12345/cards
GET
- Para leer (recuperar) la representación de un recurso.
- Si no se produce ningún error, regresa JSON (XML) y un response code 200 OK. 404 si no existe el recurso.
- Lee datos, no modifica datos.
- Idempotente, esto es, multiples llamadas GET devuelven el mismo resultado que una sola.
- No debe usarse para acciones que modifican el estado de los recursos.
Ejemplos:
- GET https://api.invexbt.com/customers/12345
- GET https://api.invexbt.com/customers/12345/offers
UPDATE
- Para actualizaciones/modificaciones.
- Recibe identificador del recurso y la representación del nuevo estado del recurso.
- Regresa un 200 OK, 404 not found, 400 Bad Request.
- No se recomienda regresar el recurso en respuesta.
- No es seguro, pero es idempotente, es decir, cambia el estado del recurso, pero las invocaciones posteriores a la primera producen el mismo estado final del recurso. No es idempotente si por ejemplo la actualización mueve un incrementador en cada llamada.
Ejemplos:
- PUT https://api.invexbt.com/customers/12345
- PUT http://api.invexbt.com/customers/12345/orders/98765
DELETE
- Se entiende su uso
- La URI contiene el identificador del recurso.
- Regresa 200 OK, 204, 404.
- Es idempotente, es decir, elimina el recurso y las invocaciones posteriores no afectan porque el recurso ya no está. Aunque la respuesta no será 200 sino 404
Ejemplos:
- DELETE http://api.invexbt.com/customers/12345/order/67
- DELETE http://www.example.com/customers/12345
Resource Naming
Diseña para los clientes, no para los datos
Nombres de recursos con significado
Es de los temas más debatidos a la hora de diseñar APIs
- Recursos bien nombrados = API intuitiva, fácil de usar
- Recursos mal nombrados = Klutsy API, difícil de usar y entender
Una RESTful API es una combinación de una colección de URIs (recursos) y operaciones sobre esas URIs (verbos HTTP), más el uso de buenas prácticas y convenciones.
Ejemplos de recursos:
- Usuarios de un sistema
- Cursos en los que un estudiante está enrolado
- Un artículo de un blog.
URIs y recursos
Cada recurso en el API tiene al menos una URI que lo identifica.
Es mejor si la URI tiene sentido y describe al recurso.
Se presentan ejemplos de nombrado correcto de recursos para un API que expone clientes, ordenes de compra, linea de productos y productos.
Buenos nombres de URIs
Para insertar (crear) un nuevo cliente en el sistema, deberíamos usar:
- POST https://api.invexbt.com/customers
Para consultar un cliente el ID# 33245:
- GET https://api.invexbt.com/customers/33245
La misma URI debería ser usada para PUT y DELETE.
Aqui una URI propuesta para crear un producto:
- POST https://api.invexbt.com/products
- GET|PUT|DELETE https://api.invexbt.com/products/66432
Buenos nombres de URIs (cont...)
Cómo relacionar un recurso OrdenDeCompra y cliente?
Primer intento:
- POST http://www.example.com/orders
Crea la orden? Sí, pero el problema es que esto no relaciona la orden con un cliente. La orden está fuera del contexto del cliente. Veamos un segundo intento:
- POST http://www.example.com/customers/33245/orders
Claramente se entiende que estamos creando una orden de compra para el cliente con ID#33245
Una jerarquía más profunda sería:
- POST http://www.example.com/customers/33245/orders/8769/lineitems
- GET http://www.example.com/customers/33245/orders/8769/lineitems/1
Nombres de URIs Anti-patterns
Así no se deben nombrar recursos.
Usar query-parameter para indicar la operacion y el verbo HTTP.
GET http://api.example.com/services?op=update_customer&id=12345&format=json
"Services" es sustantivo, pero no autodescriptivo.
Usa GET para un UPDATE. :O
Problemático (incluso peligroso) para el cliente.
Igual de peligroso es:
-
GET http://api.example.com/update_customer/12345
-
GET http://api.example.com/customers/12345/update
-
PUT http://api.example.com/customers/12345/update
Referencias
- http://www.restapitutorial.com/
- http://www.ics.uci.edu/~fielding/pubs/dissertation/rest_arch_style.htm
- https://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html
Gracias
RESTful Resource Naming
By Augusto Alonso de la Cruz Jimenez
RESTful Resource Naming
- 35