2012-07-02 24 views
13

Varios de los desarrolladores aquí están teniendo un amistoso (algunos dirían religiosa) discusión sobre si una petición GET de una API REST debe devolver el ID del recurso solicitado. Vamos a suponer que la solicitud GET siguiente:¿Debe una respuesta RESTful GET devolver el ID de un recurso?

http://my.api.com/rest/users/23

Este retorno es actualmente:

{"name": "Jim", "age": 40, "favoriteColor": "blue"} 

Tenga en cuenta que "id" no se encuentra en el conjunto de resultados.

Básicamente hay 4 campos que luchan con este problema.

CAMP # 1: Cuando los llamadores hacen la solicitud GET, ya conocen la ID. Por lo tanto, el conjunto de resultados debe incluir ID. Si las personas que llaman necesitan esta información para habilitar la edición de UI, las personas que llaman deben pasar el ID 23, quizás añadiendo el miembro {"id": 23} al JSON manualmente.
Las personas en el Campamento # 1 también argumentan que la presencia de la ID en el conjunto de resultados indicaría que este valor puede modificarse, lo que por supuesto no puede.

CAMP # 2: Sin la identificación, el conjunto de resultados JSON no se puede utilizar de forma nativa para las operaciones de edición/actualización en formularios de interfaz de usuario. En cambio, el mecanismo de devolución de llamada de AJAX debe ser responsable de pasar los campos de ID y agregarlos manualmente al conjunto de resultados. Esto parece klunky y propenso a errores. Los chicos de UI están argumentando que el conjunto de resultados "siente" que faltan datos que deberían estar presentes, es decir, la ID.

CAMP # 3: Estas personas están preocupadas por la consistencia. Si alguna vez tenemos una colección de objetos de usuario devueltos por una API, estos objetos DEBEN incluir la ID. Por lo tanto, para mayor coherencia, la versión singleton de un GET también debe incluir el ID.

CAMP # 4: Estas personas sugieren que la solicitud GET para un usuario podría devolver metadatos en forma de HyperMedia o SelfLinks que incluirían la ID.

Esto no es un esoterismo "¿Quién tiene la razón?" argumento, tampoco. El enfoque que tomemos dictará la forma de nuestra API y afectará la carga de trabajo de varios desarrolladores durante las nuevas semanas.

+1

Es solo una opinión personal, pero estoy de acuerdo con los campos 2 y 3. Creo que la representación debe contener todos los datos disponibles, identificación incluida. Particularmente cuando es una identificación natural. Esta es una pregunta muy interesante, pero dudo que encuentres una respuesta simple. – toniedzwiedz

+2

Desde la perspectiva del cliente, el URI utilizado en el GET * es * el ID. Yo votaría por el Campamento 4, suponiendo que la "ID" utilizada en el autoenlace es el URI completo, no solo la parte al final. –

+0

La gente en el Campamento 4 se sentirá aliviada al ver que no están solos. Y para confirmar, si incluyesen la ID, estaría integrada dentro de un URI completo. Esto significa que será necesario analizar el URI para extraer la ID, pero para la gente de Camp 2 al menos no tienen que cargar manualmente la carga JSON. Por otro lado, los seguidores del Campamento 1 argumentan que un URI de este tipo sería solo una implementación parcial del Nivel 3 de REST, por esta razón no les gustan los SelfLinks integrados. –

Respuesta

10

Esto es una cuestión de opinión, que no es el tipo de pregunta que Stackoverflow ama ver. en cualquier caso, ofreceré el mío.

Regresa la representación del estado de un objeto o recurso. La identificación es parte de esa representación y, por lo tanto, debe incluirse en el paquete JSON. Es una propiedad del recurso. Si la persona que llama sabe o no la identificación no es particularmente pertinente para la discusión. CAMP # 1 está en terreno inestable.

El punto que planteas sobre las colecciones es muy relevante. ¿Tiene sentido usar una representación para la operación recuperación-1 y otra representación para la operación recuperación-N? Yo creo que no.

Sin embargo, el problema que está enfrentando es más general - qué datos deben incluirse en la representación que se transfiere a los clientes, y en qué circunstancias? En algunos casos, a la persona que llama simplemente no le importa un subconjunto significativo de las propiedades. Especialmente en escenarios donde se recupera un gran conjunto de objetos, donde el costo de transmitir los datos es mayor en comparación con el costo de comunicación base, le gustaría optimizar lo que se envía de regreso.

Todos los protocolos REST suficientemente maduros tienen la capacidad de dar forma a los datos devueltos.

Para ejemplos, ver

  • la API de Facebook Graph, http://developers.facebook.com/docs/reference/api/
  • la API v2.0 StackExchange - hay un "filtro" objeto puede pasar a dar forma con precisión lo que se devuelve.
  • CouchDb API - tiene una función de mapa para cada vista, que determina qué datos se devuelven. También tiene un parámetro de consulta general, include_docs, que indica al servidor que incluya objetos completos o solo metadatos. (En algunos casos es posible que desee solamente el recuento de los datos, no los datos reales.)

Facebook permite especificar explícitamente los campos que desee.

enter image description here

El StackExchange API es interesante. Han definido un tipo de objeto completamente nuevo para respaldar la configuración. Puede usar la API para definir un "filtro" y guardarlo en el servidor. Luego, en su consulta, pasa un parámetro de filtro con el ID del filtro, y las representaciones de objetos devueltos incluyen todos los atributos especificados en el filtro. Sin filtro, obtiene un subconjunto de campos "predeterminado". Para obtener "todos los campos", necesita definir un filtro de todo incluido.

Esto se puede ver en acción en https://api.stackexchange.com/docs/answers

... y ver específicamente el diálogo de especificación de filtro.

enter image description here


No hay una sola forma correcta de hacer las cosas. Debe equilibrar la complejidad de la característica de "conformación" que admite con el costo de desarrollo y las necesidades de las aplicaciones que utilizarán la API.

+0

Gracias por la respuesta reflexiva y detallada. Pensé largo y tendido en plantear esta pregunta debido a las preocupaciones que planteaste en la primera frase: "Esta es una cuestión de opinión, que no es el tipo de Pregunta que Stackoverflow ama ver". Como destinatario de la temida insignia de "Presión entre iguales", sé muy bien lo que puede suceder con una pregunta estrictamente basada en la opinión. En mi opinión, sin embargo, este problema tiene tantas repercusiones en la programación entre los diversos Campamentos que decidí aprovechar la oportunidad. –

+1

Por mi parte, he hecho el trabajo para hacer feliz el Campamento # 1. Paso ahora una serie de pares clave/valor que puedo usar para aumentar o complementar los datos devueltos por llamadas basadas en AJAX a servicios RESTful.Esto funciona, pero simplemente no se siente bien. La gente del Campamento # 1 ha aceptado agregar la ID si yo y los otros consumidores de la API realmente queremos tener estos datos como parte de la respuesta de la carga útil GET. –

+2

Déjeme preguntarle esto: ¿Qué ocurre si la consulta no es "Obtener persona con ID = N", sino más bien "Obtener autor del documento con DOCID = Z"? Si sigues los consejos del Campamento n. ° 1, obtienes una persona objeto pero no conoces la ID de esa persona. La posición "Camp # 1" parece muy estrecha e insostenible. No tiene sentido, excepto en los escenarios más simples y poco prácticos. – Cheeso

1

vieja pregunta, pero desde que estoy aquí en busca de algo, aquí va otra opinión:

En primer lugar, creo que la URL debe ser:

http://my.api.com/rest/Users/23

no

http://my.api.com/rest/getUsers/23

El "GET" se encuentra en el método HTTP, no en la URL. Es solo nombrar, pero ayuda a hacer las cosas más claras, en mi humilde opinión.

Si se piensa en ello, una modificación de recursos tiene que suceder en la misma dirección URL con un PUT

PUT http://my.api.com/rest/Users/23

En ese caso, el cliente necesita para realizar un seguimiento de las direcciones URL, no IDs. No importa si el recurso devuelve un campo ID. Depende del cliente mantener un mapa de donde se obtuvo.

Si intenta poner un resorce a una URL diferente, dicen "http://my.api.com/rest/Users/24", se producirían una serie de escenarios:

1) http://my.api.com/rest/Users/24 ya existe en el servidor y el servidor acepta el recurso como una actualización

2) http://my.api.com/rest/Users/24 no existe en el servidor y:

a) el servidor acepta que un usuario está proporcionando un ID (24) a un recurso inexistente (no se recomienda) b) el servidor acepta un PUT como un puesto

En a + b, el servidor crearía un nuevo recurso.

Por lo tanto:

1) Dependiendo de cuánto confía en su cliente, probablemente debería crear un "check-in/check-out" de control en el servidor para evitar sobrescribir un recurso con otro (es este REST ?)

2) No debe aceptar clientes creando ID (Aceptar para publicar http://my.api.com/rest/Users/, no http://my.api.com/rest/Users/24) y no debe aceptar PUT a recursos no existentes.

EDITAR:

así que creo que el recurso se identifica por su URL, no por la ID. O, en otras palabras, el ID del recurso es http://my.api.com/rest/Users/23, no 23.

¿Tiene sentido?

+0

Acepto que fue un error insertar "obtener" en el URI. Veré si puedo modificar el OP. Gracias por la respuesta. –

+0

"Así que creo que el recurso está identificado por su URL, no por su ID". Este es el núcleo de la respuesta. Su cliente no debe construir URL, por lo tanto, a menos que la ID se use para algún otro propósito, no necesita incluirla en la respuesta ... nunca. Ni siquiera en una colección. Si desea que el cliente sepa dónde encontrar el recurso singular, proporcione una URL en lugar de una ID. Ver [HATEOAS] (http://en.wikipedia.org/wiki/HATEOAS). –

Cuestiones relacionadas