Estoy en el proceso de crear una API REST y actualmente encuentro el siguiente problema:
Foo
Es el primer recurso. Las operaciones CRUD se pueden aplicar a través del/foo/
URI.Bar
Es el segundo recurso. Las operaciones CRUD se pueden aplicar a través del/bar/
URI.- Todos
Foo
están asociados con cero o unoBar
. La razón por la que no tratoBar
como un subrecursoFoo
es porque la mismaBar
instancia se puede compartir entre variosFoo
. Así que pensé que es mejor acceder a él a través de un URI independiente en lugar de hacerlo/foo/[id]/bar
.
Mi problema es que en una cantidad significativa de casos, los clientes que solicitan una Foo
instancia también están interesados en la Bar
instancia asociada . Actualmente, esto significa que tienen que realizar dos consultas en lugar de una. Quiero presentar una forma que permita obtener ambos objetos con una sola consulta, pero no sé cómo modelar la API para hacerlo. Lo que se me ocurrió hasta ahora:
- Podría introducir un parámetro de consulta similar a esto:
/foo/[id]?include_bar=true
. El problema con este enfoque es que la representación de recursos (p. Ej., La estructura JSON) de la respuesta necesitaría verse diferente (p. Ej., Un contenedor como en{ foo: ..., bar: ... }
lugar de solo un serializadoFoo
), lo que hace que elFoo
punto final del recurso sea "heterogéneo". No creo que sea algo bueno. Al realizar consultas/foo
, los clientes siempre deben obtener la misma representación de recursos (estructura), independientemente de los parámetros de consulta. - Otra idea es introducir un nuevo punto final de solo lectura, por ejemplo
/fooandbar/[foo-id]
. En este caso, no es problema devolver una representación como{ foo: ..., bar: ... }
, porque entonces es solo la representación "oficial" delfooandbar
recurso. Sin embargo, no sé si ese punto final auxiliar es realmente RESTful (es por eso que escribí "can" en el título de la pregunta. Por supuesto, es técnicamente posible, pero no sé si es una buena idea).
¿Qué piensas? existen algunas otras posibilidades?
Bar
no puede existir sin estar asociado a aFoo
. Sin embargo, como escribí anteriormente, es posible que múltiplesFoo
correos compartan lo mismoBar
. Debería ser posible crear unFoo
sin unBar
asociado, por lo que no creoBar
que deba tratarse como padre.Respuestas:
Una API REST de nivel 3 le devolverá un
Foo
y también un enlace que indica lo relacionadoBar
.Luego puede agregar una función de "profundizar" a su API que permite la navegación de enlaces;
La función de profundización se ubicaría frente a las API e interceptaría las respuestas. Haría las llamadas de profundización y completaría los detalles antes de devolver la respuesta a la persona que llama.
Esto es algo bastante común en REST de nivel 3, ya que reduce mucho el chat del cliente / servidor sobre http lento. La compañía para la que trabajo produce una API REST de nivel 3 con exactamente esta característica.
Actualización: para lo que vale, así es como podría verse en JSON. Así es como lo estructuraría nuestra API. Tenga en cuenta que puede anidar sus desgloses para extraer enlaces de enlaces, etc.
fuente
links
matriz, cada entrada es un objeto de enlace con unrel
y unuri
campo (similar a su ejemplo xml). ¿Debo agregar un tercer campo a cada objeto de enlace (por ejemplodata
)? ¿Hay algún estándar?Si el 95% de todas las consultas quieren
Foo
, así comoBar
, a continuación, sólo tiene que devolverlo dentro delFoo
objeto cuando se solicita unaFoo
. Simplemente agregue una propiedadbar
(o algún otro término para la relación) y coloque elBar
objeto allí. Si la relación no existe, utilice nulo.Creo que estás pensando demasiado en esto :)
fuente
Foo
, y dado que cada unaBar
es bastante grande en la memoria (alrededor de 3x-4x del tamaño deFoo
), no quiero devolver un mensajeBar
si un cliente no lo solicita explícitamente.