una platzi hacer estandares ejemplo definir como caracteristicas rest pagination

platzi - estandares api rest



Carga de respuesta de paginaciĆ³n de una API RESTful (3)

Quiero apoyar la paginación en mi API RESTful.

Mi método API debe devolver una lista JSON del producto a través de /products/index . Sin embargo, hay potencialmente miles de productos, y quiero navegar a través de ellos, por lo que mi solicitud debe verse más o menos así:

/products/index?page_number=5&page_size=20

Pero, ¿cómo debe ser mi respuesta JSON? ¿Los consumidores de la API típicamente esperarían metadatos de paginación en la respuesta? ¿O solo es necesaria una variedad de productos? ¿Por qué?

Parece que la API de Twitter incluye metadatos: https://dev.twitter.com/docs/api/1/get/lists/members (ver Ejemplo de solicitud).

Con metadatos:

{ "page_number": 5, "page_size": 20, "total_record_count": 521, "records": [ { "id": 1, "name": "Widget #1" }, { "id": 2, "name": "Widget #2" }, { "id": 3, "name": "Widget #3" } ] }

Solo una variedad de productos (sin metadatos):

[ { "id": 1, "name": "Widget #1" }, { "id": 2, "name": "Widget #2" }, { "id": 3, "name": "Widget #3" } ]


Como alguien que ha escrito varias bibliotecas para consumir servicios REST, permítame darle la perspectiva del cliente sobre por qué creo que la mejor forma de encauzar el resultado en metadatos es:

  • Sin el recuento total, ¿cómo puede saber el cliente que aún no ha recibido todo lo que hay y debe continuar la búsqueda a través del conjunto de resultados? En una interfaz de usuario que no funciona mira hacia adelante a la siguiente página, en el peor de los casos esto podría representarse como un enlace Siguiente / Más que en realidad no obtuvo más datos.
  • La inclusión de metadatos en la respuesta permite al cliente rastrear menos estados. Ahora no tengo que hacer coincidir mi solicitud REST con la respuesta, ya que la respuesta contiene los metadatos necesarios para reconstruir el estado de solicitud (en este caso, el cursor en el conjunto de datos).
  • Si el estado es parte de la respuesta, puedo realizar múltiples solicitudes en el mismo conjunto de datos simultáneamente, y puedo manejar las solicitudes en cualquier orden en que lleguen, lo que no es necesariamente el orden en el que hice las solicitudes.

Y una sugerencia: al igual que la API de Twitter , debe reemplazar el número de página con un índice / cursor directo. La razón es que la API permite al cliente establecer el tamaño de la página por solicitud. ¿El número de página devuelto es el número de páginas que el cliente ha solicitado hasta el momento, o el número de la página que recibió el último tamaño de página utilizado (casi con certeza el último, pero por qué no evitar esa ambigüedad por completo)?


Las API ReSTful son consumidas principalmente por otros sistemas, razón por la cual pongo datos de paginación en los encabezados de respuesta. Sin embargo, algunos consumidores API pueden no tener acceso directo a los encabezados de respuesta, o pueden construir un UX sobre su API, por lo que proporcionar una forma de recuperar (a petición) los metadatos en la respuesta JSON es una ventaja.

Creo que su implementación debe incluir metadatos legibles por máquina de forma predeterminada y metadatos legibles por humanos cuando se solicite. Los metadatos legibles por humanos se pueden devolver con cada solicitud si lo desea o, preferiblemente, a pedido a través de un parámetro de consulta, como include=metadata o include_metadata=true .

En su escenario particular, incluiría el URI para cada producto con el registro. Esto facilita que el consumidor API cree enlaces a los productos individuales. También establecería algunas expectativas razonables según los límites de mis solicitudes de búsqueda. Implementar y documentar configuraciones predeterminadas para el tamaño de página es una práctica aceptable. Por ejemplo, la API de GitHub establece el tamaño de página predeterminado en 30 registros con un máximo de 100, además establece un límite de velocidad en la cantidad de veces que puede consultar la API. Si su API tiene un tamaño de página predeterminado, entonces la cadena de consulta solo puede especificar el índice de página.

En el escenario legible por humanos, al navegar a /products?page=5&per_page=20&include=metadata , la respuesta podría ser:

{ "_metadata": { "page": 5, "per_page": 20, "page_count": 20, "total_count": 521, "Links": [ {"self": "/products?page=5&per_page=20"}, {"first": "/products?page=0&per_page=20"}, {"previous": "/products?page=4&per_page=20"}, {"next": "/products?page=6&per_page=20"}, {"last": "/products?page=26&per_page=20"}, ] }, "records": [ { "id": 1, "name": "Widget #1", "uri": "/products/1" }, { "id": 2, "name": "Widget #2", "uri": "/products/2" }, { "id": 3, "name": "Widget #3", "uri": "/products/3" } ] }

Para los metadatos legibles por máquina, agregaría encabezados de enlace a la respuesta:

Link: </products?page=5&perPage=20>;rel=self,</products?page=0&perPage=20>;rel=first,</products?page=4&perPage=20>;rel=previous,</products?page=6&perPage=20>;rel=next,</products?page=26&perPage=20>;rel=last

(El valor del encabezado del enlace debe ser urlencoded)

... y posiblemente un encabezado de respuesta de total-count personalizado, si así lo desea:

total-count: 521

Los otros datos de búsqueda revelados en los metadatos centrados en el ser humano pueden ser superfluos para los metadatos centrados en la máquina, ya que los encabezados de los enlaces me permiten saber en qué página estoy y el número por página y puedo recuperar rápidamente el número de registros en la matriz . Por lo tanto, probablemente solo crearía un encabezado para el recuento total. Siempre puede cambiar de parecer más adelante y agregar más metadatos.

Como comentario adicional, es posible que notes que eliminé /index desde tu URI. Una convención generalmente aceptada es tener sus colecciones de exposición de puntos finales ReST. Tener /index al final se ensucia un poco.

Estas son solo algunas de las cosas que me gusta tener al consumir / crear una API. ¡Espero que ayude!


Yo recomendaría agregar encabezados para lo mismo. Mover los metadatos a los encabezados ayuda a deshacerse de los sobres como result , data o records y el cuerpo de la respuesta solo contiene los datos que necesitamos. Puede usar el encabezado de Link si también genera enlaces de paginación.

HTTP/1.1 200 Pagination-Count: 100 Pagination-Page: 5 Pagination-Limit: 20 Content-Type: application/json [ { "id": 10, "name": "shirt", "color": "red", "price": "$23" }, { "id": 11, "name": "shirt", "color": "blue", "price": "$25" } ]

Para más detalles, consulte:

https://github.com/adnan-kamili/rest-api-response-format

Para el archivo swagger:

https://github.com/adnan-kamili/swagger-response-template