El "filtro como recurso" es un tacto perfecto para esto.
Puede PONER la definición de filtro en el recurso de filtro y puede devolver la ID del filtro.
PUT es idempotente, por lo que incluso si el filtro ya está allí, solo necesita detectar que ha visto el filtro antes, para que pueda devolver la identificación adecuada para el filtro.
Luego, puede agregar un parámetro de filtro a sus otras solicitudes, y pueden tomar el filtro para usar para las consultas.
GET/medicamentos? Filter = 1,234 & page = 4 & tamaño de página = 20
correría los filtros primas a través de algún tipo de proceso de canonización, sólo para tener un conjunto normalizado, de modo que, por ejemplo, filter "firstname = Bob lastname = Eubanks" es idéntico a "lastname = Eubanks firstname = Bob". Aunque soy solo yo.
La única preocupación real es que, a medida que pasa el tiempo, es posible que tenga que obsolestar algunos filtros. Simplemente puede equivocar la solicitud en caso de que alguien haga una solicitud con un filtro faltante u obsoleto.
Editar contestador pregunta ...
Vamos a empezar con los fundamentos.
Simplemente, quiere especificar un filtro para usar en consultas, pero estos filtros son (potencialmente) complicados. Si fue simple/medicamentos/1234, esto no sería un problema.
Efectivamente, siempre debe enviar el filtro a la consulta. La pregunta es cómo representar ese filtro.
El problema fundamental con cosas como las sesiones en los sistemas REST es que normalmente se gestionan "fuera de banda". Cuando, por ejemplo, ve y creas un medicamento, PONES o PUBLICAS en el recurso de medicamentos, y obtienes una referencia de ese medicamento.
Con una sesión, normalmente recuperaría una cookie, o tal vez algún otro token para representar esa sesión. Si su PUT al recurso de medicamentos creó también una sesión, entonces, en realidad, su solicitud creó dos recursos: un medicamento y una sesión.
Desafortunadamente, cuando utiliza algo así como una cookie, y necesita esa cookie para su solicitud, el nombre del recurso ya no es la verdadera representación del recurso. Ahora es el nombre del recurso (la URL) y la cookie.
Entonces, si hago un GET en el recurso llamado/medicamentos/búsqueda, y la cookie representa una sesión, y esa sesión tiene un filtro, se puede ver cómo, en efecto, ese nombre de recurso,/medicamentos/búsqueda, no es realmente útil en absoluto. No tengo toda la información que necesito para hacer un uso efectivo, debido al efecto secundario de la cookie y la sesión y el filtro que contiene.
Ahora, quizás pueda volver a escribir el nombre:/medicines/search? Session = ABC123, incrustando efectivamente la cookie en el nombre del recurso.
Pero ahora te encuentras con el típico contrato de sesiones, especialmente que son de corta duración. Entonces, ese recurso nombrado es menos útil, a largo plazo, no inútil, solo menos útil. En este momento, esta consulta me da datos interesantes. ¿Mañana? Probablemente no. Recibiré un desagradable error acerca de que la sesión se fue.
El otro problema es que las sesiones generalmente no se administran como un recurso.Por ejemplo, generalmente son un efecto secundario, vs administrado explícitamente a través de GET/PUT/DELETE. Las sesiones también son el "montón de basura" del estado de la aplicación web. En este caso, esperamos que la sesión esté debidamente llena con lo que se necesita para esta solicitud. Realmente no sabemos realmente. Nuevamente, es un efecto secundario.
Ahora, volvamos un poco la cabeza. Usemos/medicamentos/search? Filter = ABC123.
Obviamente, casualmente, esto se ve idéntico. Acabamos de cambiar el nombre de 'sesión' a 'filtro'. Pero, como se discutió, los filtros, en este caso, SON un "recurso de primera clase". Deben crearse, administrarse, etc. de la misma manera que un medicamento, un archivo JPEG o cualquier otro recurso en su sistema. Esta es la distinción clave.
Ciertamente, podría tratar las "sesiones" como un recurso de primera clase, crearlas, poner cosas en ellas directamente, etc. Pero puede ver cómo, al menos desde el punto de vista de la claridad, una sesión de "primera clase" no es realmente una buena abstracción para este caso. Usar una sesión es como ir a la tintorería y entregar todo tu bolso o maletín. "Sí, el boleto está allí en alguna parte, excavar lo que quieras, darme mi ropa", especialmente comparado con algo explícito como un filtro.
Por lo tanto, puede ver cómo, a 30,000 pies, no hay mucha diferencia en el caso entre un filtro y una sesión. Pero cuando haces zoom, son bastante diferentes.
Con el recurso de filtro, puede optar por convertirlos en algo persistente para siempre. Puedes expirarlos, puedes hacer lo que quieras. Las sesiones tienden a tener semántica preconcebida: breve duración, duración de la conexión, etc. Los filtros pueden tener cualquier semántica que desee. Están completamente separados de lo que viene con una sesión.
Si estuviera haciendo esto, ¿cómo trabajaría con los filtros?
Supongo que realmente no me importa el contenido de un filtro. Específicamente, dudo que alguna vez busque "todos los filtros que buscan por nombre". En esta coyuntura, parece información sin interés, así que no diseñaré a su alrededor.
A continuación, normalizaría los filtros, como mencioné anteriormente. Asegúrese de que los filtros equivalentes sean realmente equivalentes. Puedes hacer esto ordenando las expresiones, asegurando que los nombres de los campos estén en mayúsculas, o lo que sea.
Luego, almaceno el filtro como un documento XML o JSON, lo que sea más cómodo/apropiado para la aplicación. Le daría a cada filtro una clave única (naturalmente), pero también almacenaría un hash para el documento real con el filtro.
Haría esto para poder encontrar rápidamente si el filtro ya está almacenado. Como lo estoy normalizando, "sé" que el XML (por ejemplo) para los filtros lógicamente equivalentes sería idéntico. Entonces, cuando alguien va a PUT, o inserta un nuevo filtro, yo verificaría el hash para ver si se había almacenado antes. Es posible que recupere más de uno (los hash pueden colisionar, por supuesto), así que tendré que comprobar las cargas útiles XML reales para ver si coinciden.
Si los filtros coinciden, devuelvo una referencia al filtro existente. Si no, crearía uno nuevo y lo devolvería.
Yo tampoco permitiría un filtro ACTUALIZAR/PUBLICAR. Como distribuyo referencias a estos filtros, los haría inmutables para que las referencias puedan seguir siendo válidas. Si quisiera un filtro por "rol", por ejemplo, el filtro "obtener todos los medicamentos vencidos", crearía un recurso de "filtro nombrado" que asocia un nombre con una instancia de filtro, para que los datos de filtro reales puedan cambiar, pero la el nombre sigue siendo el mismo
Tenga en cuenta, también, que durante la creación, está en una condición de carrera (dos solicitudes tratando de hacer el mismo filtro), por lo que tendría que dar cuenta de eso. Si su sistema tiene un alto volumen de filtro, esto podría ser un cuello de botella potencial.
Espero que esto aclare el problema para usted.
Esta es una de las mejores explicaciones que he visto por qué las sesiones no encajan bien en una arquitectura de estilo REST. –
+1: ¡Excelente respuesta, Will! –
buena explicación @ Will – jayraynet