Esta es una reformulación más genérica de esta pregunta (con la eliminación de las partes específicas de Rails)
No estoy seguro de cómo implementar la paginación en un recurso en una aplicación web RESTful. Suponiendo que tengo un recurso llamadoproducts
, ¿cuál de los siguientes crees que es el mejor enfoque y por qué?
1. Usando solo cadenas de consulta
p.ej. http://application/products?page=2&sort_by=date&sort_how=asc
El problema aquí es que no puedo usar el almacenamiento en caché de la página completa y también la URL no es muy limpia y fácil de recordar.
2. Uso de páginas como recursos y cadenas de consulta para ordenar
p.ej. http://application/products/page/2?sort_by=date&sort_how=asc
En este caso, el problema que se ve es que http://application/products/pages/1
no es un recurso único, ya que el uso sort_by=price
puede producir un resultado totalmente diferente y todavía no puedo usar el almacenamiento en caché de la página.
3. Uso de páginas como recursos y un segmento de URL para ordenar
p.ej. http://application/products/by-date/page/2
Personalmente, no veo ningún problema en usar este método, pero alguien me advirtió que no es una buena manera de hacerlo (no dio una razón, así que si sabes por qué no se recomienda, hágamelo saber)
Cualquier sugerencia, opinión, crítica es más que bienvenida. Gracias.
fuente
Respuestas:
Creo que el problema con la versión 3 es más un problema de "punto de vista": ¿ve la página como el recurso o los productos en la página?
Si ve la página como el recurso, es una solución perfecta, ya que la consulta de la página 2 siempre dará como resultado la página 2.
Pero si ve los productos en la página como el recurso, tiene el problema de que los productos en la página 2 pueden cambiar (productos antiguos eliminados, o lo que sea), en este caso, el URI no siempre devuelve los mismos recursos.
Por ejemplo, un cliente almacena un enlace a la página X de la lista de productos, la próxima vez que se abra el enlace el producto en cuestión ya no estará en la página X.
fuente
Estoy de acuerdo con Fionn, pero iré un paso más allá y diré que la página no es un recurso, es una propiedad de la solicitud. Eso me hace elegir la opción 1 cadena de consulta solamente. Simplemente se siente bien. Realmente me gusta cómo la API de Twitter está estructurada de manera tranquila. No demasiado simple, no demasiado complicado, bien documentado. Para bien o para mal, es mi diseño de "ir a" cuando estoy cerca de hacer algo de una manera u otra.
fuente
HTTP tiene un gran encabezado Range que también es adecuado para la paginación. Puedes enviar
tener solo la primera página. Eso puede obligarlo a repensar lo que es una página. Tal vez el cliente quiere una gama diferente de artículos. El encabezado de rango también funciona para declarar un pedido:
para obtener todos los productos más nuevos que esa fecha o
para obtener todos los productos anteriores a esa fecha. Probablemente '0' no sea la mejor solución, pero RFC parece querer algo para el inicio del rango. Puede haber implementados analizadores HTTP que no analizarían unidades = -range_end.
Si los encabezados no son una opción (aceptable), creo que la primera solución (todo en una cadena de consulta) es una forma de manejar las páginas. Pero, por favor, normalice las cadenas de consulta (ordena (pares = clave) pares en orden alfabético). Esto resuelve el problema de diferenciación "? A = 1 & b = x" y "? B = x & a = 1".
fuente
range-unit = bytes-unit | other-range-unit
Quizás te refieras aThe only range unit defined by HTTP/1.1 is "bytes". HTTP/1.1 implementations MAY ignore ranges specified using other units.
Eso no es lo mismo que tu declaración.La opción 1 parece la mejor, en la medida en que su aplicación ve la paginación como una técnica para producir una vista diferente del mismo recurso.
Dicho esto, el esquema de URL es relativamente insignificante. Si está diseñando su aplicación para que funcione con hipertexto funcione con (como todas las aplicaciones REST deben ser por definición), entonces su cliente no construirá ningún URI por sí solo. En cambio, su aplicación proporcionará los enlaces al cliente y el cliente los seguirá.
Un tipo de enlace que su cliente puede proporcionar es un enlace de paginación.
El efecto secundario agradable de todo esto es que, incluso si cambia de opinión sobre la estructura de URI de paginación e implementa algo totalmente diferente la próxima semana, sus clientes pueden continuar trabajando sin ninguna modificación.
fuente
Siempre he usado el estilo de la opción 1. El almacenamiento en caché no ha sido una preocupación ya que los datos cambian con frecuencia de todos modos en mi caso. Si permite que el tamaño de la página sea configurable, nuevamente los datos no se pueden almacenar en caché.
No encuentro la url difícil de recordar o impura. Para mí, este es un buen uso de los parámetros de consulta. El recurso es claramente una lista de productos y los parámetros de consulta solo indican cómo desea que se muestre la lista, ordenada y qué página.
fuente
Es extraño que nadie haya señalado que la Opción 3 tiene parámetros en un orden específico. http // application / products / Date / Descending / Name / Ascending / page / 2 y http // application / products / Name / Ascending / Date / Descending / page / 2
apuntan al mismo recurso, pero tienen URL completamente diferentes.
Para mí, la opción 1 parece la más aceptable, ya que separa claramente "Lo que quiero" y "Cómo quiero" (incluso tiene un signo de interrogación entre ellos, jajaja). El almacenamiento en caché de página completa se puede implementar utilizando una URL completa (todas las opciones sufrirán el mismo problema de todos modos).
Con el enfoque de Parámetros en URL, el único beneficio es una URL limpia. Aunque tiene que encontrar alguna forma de codificar parámetros y decodificarlos sin pérdidas. Por supuesto, puedes usar URLencode / decode, pero volverá a poner las URL feas de nuevo :)
fuente
Prefiero usar los parámetros de consulta offset y limit.
offset : para el índice del artículo en la colección.
límite : para el recuento de artículos.
El cliente simplemente puede seguir actualizando el desplazamiento de la siguiente manera
para la página siguiente
La ruta se considera el identificador del recurso. Y una página no es un recurso sino un subconjunto de la colección de recursos. Dado que la paginación es generalmente una solicitud GET, los parámetros de consulta son más adecuados para la paginación que para los encabezados.
Referencia: https://metamug.com/article/rest-api-developers-dilemma.html#Requesting-the-next-page
fuente
Buscando las mejores prácticas me encontré con este sitio:
http://www.restapitutorial.com
En la página de recursos hay un enlace para descargar un archivo .pdf que contiene las mejores prácticas REST completas sugeridas por el autor. En el que, entre otras cosas, hay una sección sobre paginación.
El autor sugiere agregar soporte tanto para usar un encabezado Range como para usar parámetros de cadena de consulta.
Solicitud
Ejemplo de encabezado HTTP:
Ejemplo de parámetros de cadena de consulta:
Donde offset es el número de artículo inicial y el límite es el número máximo de artículos a devolver.
Respuesta
La respuesta debe incluir un encabezado de rango de contenido que indique cuántos elementos se devuelven y cuántos elementos totales aún no se han recuperado
Ejemplos de encabezado HTTP:
En el .pdf hay algunas otras sugerencias para casos más específicos.
fuente
Actualmente estoy usando un esquema similar a este en mis aplicaciones ASP.NET MVC:
p.ej
http://application/products/by-date/page/2
específicamente es:
http://application/products/Date/Ascending/3
Sin embargo, no estoy realmente contento con incluir información de paginación y clasificación en la ruta de esta manera.
La lista de artículos (productos en este caso) es mutable. es decir, la próxima vez que alguien regrese a una url que incluye parámetros de paginación y clasificación, los resultados que obtienen pueden haber cambiado. Por lo tanto
http://application/products/Date/Ascending/3
, se pierde la idea de una URL única que apunta a un conjunto de productos definido e inmutable.fuente
Tiendo a estar de acuerdo con slf en que "página" no es realmente un recurso. Por otro lado, la opción 3 es más limpia, más fácil de leer y el usuario puede adivinarla más fácilmente e incluso escribirla si es necesario. Estoy dividido entre las opciones 1 y 3, pero no veo ninguna razón para no usar la opción 3.
Además, aunque se ven bien, una desventaja de usar parámetros ocultos, como alguien mencionó, en lugar de cadenas de consulta o segmentos de URL es que el usuario no puede marcar o vincular directamente a una página en particular. Eso puede o no ser un problema dependiendo de la aplicación, pero solo algo a tener en cuenta.
fuente
He usado la solución 3 antes (escribo MUCHAS aplicaciones de django). Y no creo que haya nada malo en ello. Es tan generable como los otros dos (en caso de que necesite hacer un raspado en masa o similar) y se ve más limpio. Además, sus usuarios pueden adivinar las URL (si es una aplicación pública), y a las personas les gusta poder ir directamente a donde quieran, y adivinar las url se siente fortalecedor.
fuente
Utilizo en mis proyectos las siguientes URL:
lo que significa: "dame la segunda página ordenada ascendente por campo1 y luego descendente por campo2". O si necesito aún más flexibilidad, uso:
fuente
Utilizo los siguientes patrones para obtener el siguiente registro de página. http: // application / products? lastRecordKey =? & pageSize = 20 & sort = ASC
RecordKey es la columna de una tabla que contiene un valor secuencial en DB. Esto se usa para obtener solo datos de una página a la vez desde DB. pageSize se utiliza para determinar cuántos registros recuperar. sort se usa para ordenar el registro en orden ascendente o descendente.
fuente