Diferencia entre revisiones de «Buenas prácticas API Rest»
([feat] Add information about Buenas prácticas API Rest) |
([feat] Add information about Buenas prácticas API Rest) |
||
Línea 53: | Línea 53: | ||
Una vez que liberes una API pública, te comprometes a no romper cosas sin previo aviso. La documentación debe incluir información y detalles sobre futuras actualizaciones a la API que sean visibles al exterior. Las actualizaciones deben ser entregadas a través de un blog (es decir, una lista de cambios) o una lista de correo (preferiblemente ambos). | Una vez que liberes una API pública, te comprometes a no romper cosas sin previo aviso. La documentación debe incluir información y detalles sobre futuras actualizaciones a la API que sean visibles al exterior. Las actualizaciones deben ser entregadas a través de un blog (es decir, una lista de cambios) o una lista de correo (preferiblemente ambos). | ||
= Versionado = | |||
Siempre versiona tu API y debería de ser incluida en la URL. El versionado te ayuda a iterar más rápido y evitar peticiones inválidas desde endpoints actualizados. Además te ayuda a resolver cualquier transición importante de versión de la API mientras continúas ofreciendo viejas versiones de la API por un período de tiempo. | |||
Una API nunca va a ser completamente estable. El cambio es inevitable. Lo importante es cómo se gestiona el cambio. | |||
= Filtrado, ordenación y búsqueda en los resultados = | |||
Lo mejor es mantener la URL base de recursos tan simple como sea posible. Filtros de resultados complejos, requisitos de ordenamiento y búsqueda avanzada (cuando se limita a un solo tipo de recurso) pueden ser implementados fácilmente como parámetros de consulta en la parte superior de la URL base. | |||
== Filtrado == | |||
Usa un único parámetro de consulta por cada campo que implemente el filtro. | |||
=== Ejemplo === | |||
Cuando se pide una lista de tickets del endpoint /tickets, podrías querer limitarla a sólo los que están en estado abierto. Esto puede ser logrado con una petición como: | |||
GET /tickets?state=open. | |||
En este caso, state es el parámetro de la consulta que implementa el filtro. | |||
== Ordenación == | |||
Similar al filtrado, un parámetro genérico sort puede ser usado para describir el ordenamiento. Organiza los requerimientos de ordenamiento complejos permitiendo que el parámetro de ordenación sea tomado de una lista de campos separados por coma, cada uno con un posible negativo unario para implicar orden descendiente. | |||
=== Ejemplos === | |||
GET /tickets?sort=-priority – Devuelve una lista de tickets en orden de prioridad descendiente | |||
GET /tickets?sort=-priority,created_at- Devuelve una lista de tickets en orden de prioridad descendiente. Con una prioridad específica, los tickets más viejos son ordenados primero. | |||
== Búsqueda == | |||
A veces los filtros básicos no son suficientes y se necesita la posibilidad de realizar una búsqueda completa sobre el texto. | |||
El parámetro utilizado es '''q'''. Las consultas de búsqueda deberían ser pasadas directamente al motor de búsqueda (elasticsearch por ejemplo) y la salida de la API deberían estar en el mismo formato que un lista de resultado normal. | |||
=== Ejemplos === | |||
GET /tickets?q=return&state;=open&sort;=-priority,created_at – Devuelve el ticket abierto de mayor prioridad que menciona la palabra ‘return’ | |||
= Alias consultas comunes = | |||
== Ejemplo == | |||
La consulta de tickets cerrados recientemente puede ser empaquetada como: | |||
GET /tickets/recently_closed. | |||
= Extras = | = Extras = | ||
* Provee una forma de limitar cuáles campos son devueltos desde la API. | * Provee una forma de limitar cuáles campos son devueltos desde la API. | ||
* Devuelve algo útil de las peticiones POST, PATCH & PUT. | * Devuelve algo útil de las peticiones POST, PATCH & PUT. |
Revisión del 14:10 20 ago 2022
General
Una API es una interfaz de usuario (UI) para un desarrollador, al igual que cualquier UI, es importante asegurar que la experiencia del usuario esté pensada cuidadosamente!
Usa acciones y URLs RESTful
Los fundamentales principios de REST se basan en separar tu API en recursos lógicos. Estos recursos son manipulados usando peticiones HTTP donde el método (GET, POST, PUT, PATCH, DELETE) tienen un significado específico.
¿Pero qué puede hacer un recurso? Bueno, estos deberían ser sustantivos (¡no verbos!) que tengan sentido desde una perspectiva del consumidor de la API. Aunque tus modelos internos pueden mapear cuidadosamente con los recursos, no es necesario que sea un mapeo uno-a-uno.
Una vez que tienes tus recursos definidos, necesitas identificar qué acciones aplican a ellos y cómo deberían relacionarse con tu API. Los principios REST proveen estrategias para manejar acciones CRUD usando métodos HTTP relacionados de la siguiente forma:
GET /tickets- Devuelve una lista de tickets GET /tickets/12- Devuelve un ticket específico POST /tickets- Crea un nuevo ticket PUT /tickets/12- Actualiza el ticket #12 PATCH /tickets/12- Actualiza parcialmente el ticket #12 DELETE /tickets/12- Elimina el ticket #12
Siempre usar plural para los recursos.
Ejemplos
/tickets /tickets/12
Relaciones
¿Pero cómo lidiar con las relaciones? Si una relación puede existir con un sólo recurso, los principios REST proveen una guía útil. Veamos esto con un ejemplo. Un ticket consiste en un número de mensajes. Estos mensajes pueden ser lógicamente mapeados al endpoint /tickets de la siguiente forma:
GET /tickets/12/messages - Devuelve una lista de mensajes para el ticket #12 GET /tickets/12/messages/5 - Devuelve el mensaje #5 para el ticket #12 POST /tickets/12/messages - Crea un nuevo mensaje en el ticket #12 PUT /tickets/12/messages/5 – Actualiza el mensaje #5 para el ticket #12 PATCH /tickets/12/messages/5 - Actualiza parcialmente el mensaje #5 para el ticket #12 DELETE /tickets/12/messages/5 - Borra el mensaje #5 para el ticket #12
Obervaciones
A veces realmente no tienes forma de mapear la acción a una estructura REST apropiada.
Por ejemplo, una búsqueda multi-recurso no tiene sentido ser asignada a un endpoint de un recurso específico. En este caso, /search podría tener más sentido incluso si no es un sustantivo. Esto está BIEN – sólo realiza lo que sea correcto desde la perspectiva del consumidor de la API y asegúrate de que esté claramente documentado para evitar confusiones.
SSL
Usa siempre SSL, sin excepciones. Las APIs web pueden ser accedidas desde cualquier lado donde haya internet (como librerías, cafeterías, aeropuertos, entre otros). No todos son seguros. Muchos no encriptan las comunicaciones, permitiendo fácilmente ser espiados o falsificados si son interceptadas las credenciales de autenticación.
Documentación
Una API es buena tanto como lo sea su documentación. Los docs deberían ser fáciles de encontrar y de acceso público.
Los documentos deberían mostrar ejemplos de ciclos completos de petición/respuesta. Preferentemente, las peticiones deberían poder ser "pegadas" – tanto los hipervínculos deberían poder ser pegados en un navegador como los ejemplos de código deberían poder ser pegados en una consola. GitHub y Strip hacen un muy buen trabajo en este aspecto.
Una vez que liberes una API pública, te comprometes a no romper cosas sin previo aviso. La documentación debe incluir información y detalles sobre futuras actualizaciones a la API que sean visibles al exterior. Las actualizaciones deben ser entregadas a través de un blog (es decir, una lista de cambios) o una lista de correo (preferiblemente ambos).
Versionado
Siempre versiona tu API y debería de ser incluida en la URL. El versionado te ayuda a iterar más rápido y evitar peticiones inválidas desde endpoints actualizados. Además te ayuda a resolver cualquier transición importante de versión de la API mientras continúas ofreciendo viejas versiones de la API por un período de tiempo.
Una API nunca va a ser completamente estable. El cambio es inevitable. Lo importante es cómo se gestiona el cambio.
Filtrado, ordenación y búsqueda en los resultados
Lo mejor es mantener la URL base de recursos tan simple como sea posible. Filtros de resultados complejos, requisitos de ordenamiento y búsqueda avanzada (cuando se limita a un solo tipo de recurso) pueden ser implementados fácilmente como parámetros de consulta en la parte superior de la URL base.
Filtrado
Usa un único parámetro de consulta por cada campo que implemente el filtro.
Ejemplo
Cuando se pide una lista de tickets del endpoint /tickets, podrías querer limitarla a sólo los que están en estado abierto. Esto puede ser logrado con una petición como:
GET /tickets?state=open.
En este caso, state es el parámetro de la consulta que implementa el filtro.
Ordenación
Similar al filtrado, un parámetro genérico sort puede ser usado para describir el ordenamiento. Organiza los requerimientos de ordenamiento complejos permitiendo que el parámetro de ordenación sea tomado de una lista de campos separados por coma, cada uno con un posible negativo unario para implicar orden descendiente.
Ejemplos
GET /tickets?sort=-priority – Devuelve una lista de tickets en orden de prioridad descendiente GET /tickets?sort=-priority,created_at- Devuelve una lista de tickets en orden de prioridad descendiente. Con una prioridad específica, los tickets más viejos son ordenados primero.
Búsqueda
A veces los filtros básicos no son suficientes y se necesita la posibilidad de realizar una búsqueda completa sobre el texto.
El parámetro utilizado es q. Las consultas de búsqueda deberían ser pasadas directamente al motor de búsqueda (elasticsearch por ejemplo) y la salida de la API deberían estar en el mismo formato que un lista de resultado normal.
Ejemplos
GET /tickets?q=return&state;=open&sort;=-priority,created_at – Devuelve el ticket abierto de mayor prioridad que menciona la palabra ‘return’
Alias consultas comunes
Ejemplo
La consulta de tickets cerrados recientemente puede ser empaquetada como:
GET /tickets/recently_closed.
Extras
- Provee una forma de limitar cuáles campos son devueltos desde la API.
- Devuelve algo útil de las peticiones POST, PATCH & PUT.
- Usa JSON donde sea posible, XML sólo si tienes la obligación.
- Deberías usar camelCase con JSON, pero snake_case es un 20% más fácil de leer.
- Usa Pretty Print por defecto y asegura que gzip esté soportado.
- No uses respuestas encapsuladas por defecto.
- Considera usar JSON para cuerpos de peticiones POST, PUT y PATCH.
- Provee encabezados de respuesta útiles para controles de tráfico (rate limiting).
- Usa autenticación basada en tokens.
- Incluir encabezados de respuesta que faciliten el caché.
- Define un error de carga útil (payload) que sea consumible
- Utilizar efectivamente los códigos de error HTTP