Consejos y mejores prácticas de desarrollo de API REST - Parte 3

Consejos y mejores prácticas de desarrollo de API REST - Parte 3

@programacion

DOCUMENTACIÓN

Al igual que con cualquier tipo de proyecto de software, una buena documentación contribuye en gran medida a aumentar la adopción de su API más rápidamente.

Las dos opciones más populares de la sección Especificación del primer artículo de esta serie también pueden acudir en su ayuda como opciones de documentación. Si ha adoptado la OEA , ya tiene una gran solución para la documentación y las pruebas manuales integradas de su API en forma de Swagger UI .

La aplicación Postman proporciona características similares en esta área y, como último recurso, siempre tiene la opción de generar su propia documentación desde cero (aunque será más difícil de mantener y carecerá de un entorno de prueba integrado).

1. No olvide los errores

Si bien los consumidores pueden determinar fácilmente los recursos y el esquema de su API con escasa información y algunas solicitudes de prueba, los errores que devuelve su API pueden ser más difíciles de descubrir. Debe documentarlos todos en detalle, en combinación con los puntos finales que pueden devolverlos y/o las condiciones que harán que sucedan.

La experiencia muestra que los errores son una de las primeras cosas en la documentación que los equipos no actualizan para reflejar los cambios en su código (cuando el flujo de trabajo no utiliza un enfoque de especificación primero, como OAS o similar).

2. Referencia de entidad

Si su aplicación es lo suficientemente grande, es probable que su API devuelva varios tipos de entidades que a veces pueden tener relaciones complejas entre ellas. Algunas de esas entidades probablemente crecerán lo suficiente como para contener una gran cantidad de datos que es posible que no desee devolver en cada llamada.

El filtrado de campos puede devolver una vista filtrada predeterminada de sus objetos que solo enumera algunos de sus atributos disponibles, por lo que no brinda a los consumidores una descripción general completa de cada entidad con una simple solicitud.

En tales casos, es preferible tener un índice completo e independiente de entidades disponibles que los desarrolladores puedan examinar para eliminar la ambigüedad del uso de cada campo y las relaciones entre las entidades. Además, si no proporciona un SDK o un conjunto de objetos comerciales, es un recurso excelente que pueden utilizar para desarrollar su propio conjunto de modelos de datos en el cliente.

3. Historial de versiones

https://pixabay.com/es/photos/cartas-viejas-pluma-fotos-antiguas-1082299/

Este es realmente importante para asegurarse de que sus clientes estén siempre actualizados. Puede agregar actualizaciones incrementales ininterrumpidas a su API sin tener que desaprobar su versión principal (haciendo aumentos de versiones menores), pero debe comunicarlas claramente a sus consumidores.

Debe mantener una versión de documentación separada para cada nueva versión de su API (incluso las menores) todavía disponible en producción. De esa manera, sus consumidores pueden realizar un seguimiento de sus cambios lo más rápido posible y aprovecharlos en la próxima versión de sus aplicaciones cliente, incluso si se saltaron algunas versiones menores.

Los registros de cambios fácilmente disponibles entre versiones también son excelentes para proporcionar una descripción general rápida de todas las actualizaciones.

MÁS ALLÁ DE LO BÁSICO

En esta sección, mencionaré algunas características no tan básicas que he encontrado muy útiles a lo largo de los años y que no veo mencionadas con tanta frecuencia.

https://pixabay.com/es/photos/t%c3%banel-final-arquitectura-pasaje-2033982/

1. HATEOAS

Aunque la disertación de tesis de Roy Fielding sobre estados que no hay descanso sin HATEOAS , y la gente va tan lejos como para las llamadas de API que no lo soportan, hay un número creciente de personas que se encuentran hablando sobre la problemática de HATEOAS ( ligeramente hablando).

Hasta hace unos años, adopté un enfoque estrictamente pragmático para el diseño de API REST . Tener que trabajar en proyectos más grandes con una larga historia y terribles problemas de versiones me hizo reevaluar mi enfoque. Si bien todavía soy escéptico sobre si la hinchazón de HAL o los formatos hipermedia alternativos tienen mucho sentido, aprecio las soluciones prácticas como el uso de hipermedia de GitHub (aunque GitHub se ha trasladado a GraphQL para la última versión de su API).

No afirmaré que tengo un conocimiento perfecto de HATEOAS y lo que todas sus ventajas promocionadas pueden hacer por una API en la práctica, pero he llegado a apreciar algunas de ellas. Todavía no he visto el cliente ideal, uno que funcione simplemente conociendo la URL base de la API, pero puede deberse a que no he buscado lo suficiente.

2. Almacenamiento en caché

El protocolo HTTP ha admitido mecanismos de almacenamiento en caché desde los primeros años de la web con diversos grados de éxito. Aunque el estándar de protocolo inicial podría mejorarse, las fallas a menudo se atribuían a una mala configuración del servidor o implementaciones inadecuadas de servidores o clientes (incluidos los primeros navegadores web).

Nos acercamos al final de 2018 y HTTP 1.1 está disponible casi universalmente, con la adopción de HTTP 2.0 aumentando rápidamente, sin embargo, muchas API web (no las de las principales empresas) siguen ignorando por completo los mecanismos de almacenamiento en caché de protocolos estándar. En el mejor de los casos, los clientes intentarán utilizar su propio enfoque de almacenamiento en caché (a través de parámetros implícitos proporcionados en las respuestas de las API) y, en el peor de los casos, no habrá almacenamiento en caché en absoluto.

La situación anterior suena mal, pero empeora aún más teniendo en cuenta que toda la infraestructura de almacenamiento en caché de protocolos funciona automáticamente para la mayoría de los clientes (navegadores, bibliotecas de redes nativas, etc.), ¡siempre que las API devuelvan los encabezados de almacenamiento en caché adecuados! Si eso no parece mucho trabajo, ayude a mejorar la web utilizando el almacenamiento en caché en su API.

No entraré en todos los detalles sobre los mecanismos de almacenamiento en caché de HTTP, ya que hay muchos recursos que puede leer en línea, pero si sabe lo que significa el almacenamiento en caché en general, implementarlo en este contexto es mucho más fácil de lo que piensa. Todo lo que tiene que hacer es informar al cliente si puede almacenar en caché una respuesta y cuándo espera que su contenido cambie (y por lo tanto invalide el caché).

Si desea que el cliente almacene en caché una determinada respuesta, pero no está seguro de cuándo podría cambiar, no haga que descarguen todo el cuerpo de la respuesta cada vez. Solo usa ETags y solo tendrás que dar una breve respuesta que les permita saber si el contenido que solicitaron ha cambiado o no, desde la última vez que lo descargaron. Finalmente, a menos que tenga que admitir clientes realmente antiguos, puede omitir los mecanismos de caché HTTP 1.0 por completo (aunque debería ser trivial de implementar si hizo todo lo demás correctamente).

3. Limitación de frecuencia

A menudo, la limitación de velocidad es una de las últimas cosas que implementan los desarrolladores de API, generalmente después de que se ha informado de algún tipo de abuso del servicio. Creo que debería ser una parte integral de cualquier API que sirva a más de un puñado de usuarios y debería implementarse con cuidado.

Un error común que cometen los desarrolladores es confiar en implementaciones ingenuas que solo han sido probadas por un par de personas durante el desarrollo. ¡No te dejes engañar! Es probable que un algoritmo simple que mida las visitas por una dirección IP en relación con el tiempo provoque una denegación masiva de servicio para su nuevo gran cliente B2B, que utiliza un espacio IP limitado para sus clientes de red. Siempre tener en cuenta las fichas de autorización y ser muy cuidadoso acerca de cómo implementar la limitación de velocidad - o no hacerlo en absoluto antes de haber educado a sí mismo y pensó en todas las posibles consecuencias.

Si su API implementa la limitación de velocidad, asegúrese de informar a sus consumidores proporcionando su estado actual a través de encabezados de respuesta. Consulte algunos ejemplos de Twitter y GitHub si necesita inspiración.

4. Conjuntos de campos dispersos/filtrado de campos

Ser capaz de reducir la información que un cliente recibe del servidor es un tema que no suele surgir hasta que la respuesta inflada ya es considerable. Tal vez sus objetos de respuesta se hayan escalado a cientos de campos, o tal vez tengan pocos, pero uno de ellos contiene cientos de kilobytes de texto o HTML. En tales casos, se puede limitar el tamaño de sus respuestas dividiendo los datos en diferentes puntos finales, pero a menudo eso no es práctico debido a los clientes existentes u otras razones.

Un enfoque diferente y, a veces, mejor es proporcionar un mecanismo común para filtrar los campos de respuesta para todos los puntos finales. Las solicitudes de sus clientes podrían especificar qué campos quieren que devuelva en su respuesta, o incluso cuáles quieren que excluya (lo ideal es que proporcione ambas funciones).

Este concepto de respuestas parciales no es nuevo; sin embargo, es muy útil para API grandes o clientes con conexiones lentas o intermitentes (como dispositivos móviles). Las alternativas más nuevas a REST, como GraphQL , se basan en gran medida en esta idea de obtener solo lo que necesita de su API (GraphQL lleva muchos pasos más allá).

Este es un enfoque que siempre me ha gustado:

Tiene un parámetro de solicitud fields que le permite especificar los nombres de todos los campos que desea devolver, utilizando puntos para indicar el anidamiento. Si los campos que desea excluir son menos de los que necesita incluir, puede especificarlos usando un signo menos delante de sus nombres.

He aquí un ejemplo sencillo:

Digamos que tenemos el GET /articlespunto final que devuelve una lista de artículos de periódicos.

Cada artículo contiene metadatos como su titleauthordateetc. También contiene una synopsisy el texto del artículo real en HTML dentro del campo huge_html_content.

Cuando nuestra aplicación cliente de periódicos necesita mostrar la lista de todos los artículos más recientes, no es necesario que incluya el texto completo de cada artículo. Solo sus metadatos y sinopsis deberían ser suficientes. En ese caso, todo lo que tenemos que hacer es excluir el campo huge_html_content de la respuesta mediante la siguiente solicitud.

GET /articles?fields=-huge_html_content

Alternativamente, podríamos lograr lo mismo solicitando todos los campos sin el campo huge_html_content pero eso haría una solicitud más larga:

GET /articles?fields=title,author,date,synopsis

Asumamos que el authorcampo contiene un objeto anidado con campos tales como las del autor del artículo nameemailbioDado que solo mostraremos una lista de artículos, todo lo que necesitamos es el nombre del autor. El resto de los campos del autor son irrelevantes.

En ese caso, la solicitud anterior se convierte en:

GET /articles?fields=author.name,-huge_html_content

Tenga en cuenta que podemos incluir y excluir campos por nivel de anidamiento, por lo que lo anterior especifica que queremos todos los campos en el objeto raíz excepto huge_html_content , y solo el campo name dentro del objeto de autor anidado.

5. Paginación avanzada

El enfoque más común para reducir la cantidad de datos que recibe un cliente es la paginación. La combinación habitual de parámetros de compensación/límite ha existido durante décadas en SQL y la web la ha adoptado casi sin cambios. Lo más probable es que lo necesite mucho en su API, así que asegúrese de implementarlo correctamente.

El encabezado del enlace

El encabezado del enlace es una de esas tecnologías web que se especifica de una manera muy abstracta y académica en su RFC, pero en la práctica, no se ve que se use con tanta frecuencia. Cuando se usa en el espíritu de HATEOAS, debería aumentar la visibilidad de su API por parte de sus clientes, acercarla a la auto-documentación y ayudar a que el control de versiones sea cosa del pasado.

Si lo anterior le suena demasiado abstracto, lo que hace básicamente el encabezado del enlace; Proporciona enlaces para recuperar el resto de los datos que no fueron devueltos por la solicitud actual (paginada). Podría proporcionar enlaces a las páginas de datos siguientes y anteriores e incluso agregar enlaces a la primera y última página, como lo hace GitHub .

Colecciones de rápido crecimiento

Cuando necesite combinar la paginación con colecciones de datos que reciben constantemente nuevas entradas, los parámetros habituales limit/offset paginación resultarán ineficaces. Cada vez que se agrega una nueva entrada al inicio de la colección, se invalida el offset que se envió previamente al cliente, ya que se habrá movido un lugar. Además, el cliente no tiene forma de saber cuántas entradas nuevas se agregaron entre dos solicitudes.

Un mejor enfoque para mantener a los clientes sincronizados, mientras que al mismo tiempo se limita el tamaño de la respuesta para cada solicitud a través de la paginación, es utilizar los identificadores únicos del registro más nuevo o más antiguo disponible en el cliente. Este enfoque solo funciona cuando hay identificadores únicos disponibles para cada registro y combina el parámetro limit con los parámetros before_idy after_id en lugar del parámetro offset habitual .

Por tanto, el cliente puede utilizar:

  • O el ID de la entrada más antigua que conoce (última entrada en la última respuesta) como el parámetro de solicitud before_id, cuando necesita la siguiente página de entradas (más antiguas) (creada antes de la entrada más antigua que conoce el cliente).
  • O el ID de la entrada más reciente que conoce (primera entrada en la primera respuesta) como el parámetro de solicitud after_id, para recuperar una página de nuevas entradas que se crearon después de la entrada más nueva que conoce.

6. Encabezado Accept-Language

Este encabezado de solicitud muy importante y omnipresente tiende a pasarse por alto con bastante frecuencia, aunque es muy útil. Lo que básicamente hace es proporcionar una lista de idiomas que el cliente admite (en orden de preferencia) al servidor.

He visto muchas API que utilizan un parámetro personalizado para la selección de idioma e ignoran este encabezado, aunque la mayoría de los clientes envían el encabezado de forma predeterminada (respetando las preferencias de localización del usuario final). Puede usar esto cuando su API necesite proporcionar cualquier tipo de contenido localizado.

Fuente:

https://medium.com/epignosis-engineering/rest-api-development-tips-and-best-practices-part-1-9cbd4b924285

https://medium.com/epignosis-engineering/rest-api-development-tips-and-best-practices-part-2-d3ae4a13cbb7

https://medium.com/epignosis-engineering/rest-api-development-tips-and-best-practices-part-3-79c14a88f76b

Report Page