Necesito diseñar una API de consulta RESTful, que devuelva un conjunto de objetos basados en unos pocos filtros. El método HTTP habitual para esto es GET. El único problema es que puede tener al menos una docena de filtros, y si los pasamos todos como parámetros de consulta, la URL puede ser bastante larga (lo suficiente como para ser bloqueada por algún firewall).
Reducir el número de parámetros no es una opción.
Una alternativa que se me ocurre es utilizar el método POST en el URI y enviar los filtros como parte del cuerpo POST. ¿Es esto en contra de ser RESTfull (Hacer una llamada POST para consultar datos).
¿Alguien tiene alguna sugerencia de diseño mejor?
api
rest
http-parameters
missionE46
fuente
fuente
Respuestas:
Recuerde que con una API REST, todo se trata de su punto de vista.
Los dos conceptos clave en una API REST son los puntos finales y los recursos (entidades). En términos generales, un punto final devuelve recursos a través de GET o acepta recursos a través de POST y PUT y así sucesivamente (o una combinación de los anteriores).
Se acepta que con POST, los datos que envíe pueden o no resultar en la creación de un nuevo recurso y sus puntos finales asociados, que probablemente no "vivan" bajo la URL POSTed. En otras palabras, cuando PUBLICA, envía datos a algún lugar para su manejo. El punto final POST no es donde normalmente se puede encontrar el recurso.
Citando de RFC 2616 (con partes irrelevantes omitidas y partes relevantes resaltadas):
Nos hemos acostumbrado a los puntos finales y los recursos que representan 'cosas' o 'datos', ya sea un usuario, un mensaje, un libro, cualquiera que sea el dominio del problema. Sin embargo, un punto final también puede exponer un recurso diferente, por ejemplo, resultados de búsqueda.
Considere el siguiente ejemplo:
Este es un CRUDO DE RESTO típico. Sin embargo, ¿qué pasa si agregamos:
No hay nada RESTful sobre este punto final. Acepta datos (entidad) en la forma del cuerpo de la solicitud. Esos datos son los criterios de búsqueda , un DTO como cualquier otro. Este punto final produce un recurso (entidad) en respuesta a la solicitud: Resultados de búsqueda . El recurso de resultados de búsqueda es temporal, se sirve inmediatamente al cliente, sin redireccionamiento y sin exponerse desde alguna otra URL canónica.
Todavía es REST, excepto que las entidades no son libros: la entidad de solicitud es el criterio de búsqueda de libros y la entidad de respuesta son los resultados de búsqueda de libros.
fuente
BooksSearchCriteriaDTO
yBooksSearchResultsDTO
.POST
se usa para la parte C de CRUD. Iría con el viejo y simple 200, opcionalmente con 204 para los resultados de búsqueda vacíos.Mucha gente ha aceptado la práctica de que un GET con una cadena de consulta demasiado larga o demasiado compleja (por ejemplo, las cadenas de consulta no manejan datos anidados fácilmente) puede enviarse como una POST, con los datos complejos / largos representados en el cuerpo de la solicitud.
Busque la especificación POST en la especificación HTTP. Es increíblemente amplio. (Si quieres navegar en un acorazado a través de una escapatoria en REST ... usa POST).
Pierde algunos de los beneficios de la semántica GET ... como reintentos automáticos porque GET es idempotente, pero si puede vivir con eso, podría ser más fácil aceptar el procesamiento de consultas realmente largas o complicadas con POST.
(jajaja digresión larga ... Hace poco descubrí que por la especificación HTTP, GET puede contener un cuerpo de documento. Hay una sección que dice, parafraseando, "Cualquier solicitud puede tener un cuerpo de documento excepto los enumerados en esta sección" ... y la sección a la que hace referencia no enumera ninguno. Busqué y encontré un hilo donde los autores de HTTP hablaban de eso, y fue intencional, para que los enrutadores y demás no tuvieran que diferenciar entre diferentes mensajes. Sin embargo, en practique muchas piezas de infraestructura y deje caer el cuerpo de un GET. Entonces podría hacerlo con filtros representados en el cuerpo, como POST, pero estaría tirando los dados).
fuente
En pocas palabras: haga una POST pero anule el método HTTP utilizando el encabezado X-HTTP-Method-Override .
Solicitud real
POST / libros
Cuerpo de la entidad
{"title": "Ipsum", "year": 2017}
Encabezados
X-HTTP-Method-Override: GET
En el lado del servidor, verifique si el encabezado X-HTTP-Method-Override existe y luego tome su valor como el método para construir la ruta al punto final final en el back-end. Además, tome el cuerpo de la entidad como la cadena de consulta. Desde el punto de vista del backend, la solicitud se convirtió en un simple GET.
De esta manera, mantiene el diseño en armonía con los principios REST.
Editar: Sé que esta solución originalmente estaba destinada a resolver el problema del verbo PATCH en algunos navegadores y servidores, pero también funciona para mí con el verbo GET en el caso de una URL muy larga, que es el problema descrito en la pregunta.
fuente
X-
eliminación existente y 1.5. no anula las especificaciones existentes. ...X-
OMI permanecerá aquí.Si está desarrollando en Java y JAX-RS, le recomiendo que use @QueryParam con @GET
Tenía la misma pregunta cuando necesitaba revisar una lista.
Ver ejemplo:
Patrón URI: "poc / test? Code = 1 & code = 2 & code = 3
@QueryParam convertirá el parámetro de consulta "orderBy = age & orderBy = name" en java.util.List automáticamente.
fuente