DESIGN DESIGN DESIGN – Obtener un recurso a través de REST con diferentes parámetros pero el mismo patrón de URL

Tengo una pregunta relacionada con el diseño de URL REST. Encontré algunas publicaciones relevantes aquí: Diferentes representaciones RESTful del mismo recurso y aquí: URL RESTful para OBTENER recursos por diferentes campos, pero las respuestas no son muy claras sobre cuáles son las mejores prácticas y por qué. Aquí hay un ejemplo.

Tengo URLs REST para representar recursos de “usuarios”. Puedo OBTENER un usuario con una identificación o una dirección de correo electrónico, pero la representación de URL sigue siendo la misma para ambos. Al revisar muchos blogs y libros, veo que la gente ha estado haciendo esto de diferentes maneras. Por ejemplo

lee esta práctica en un libro y en algún lugar en stackoverflow (parece que no puedo encontrar el enlace nuevamente)

GET /users/id={id} GET /users/email={email} 

lee esta práctica en muchos blogs

 GET /users/{id} GET /users/email/{email} 

Los parámetros de consulta se usan normalmente para filtrar los resultados de los recursos representados por la url, pero también he visto que esta práctica se usa

 GET /users?id={id} GET /users?email={email} 

Mi pregunta es, de todas estas prácticas, ¿cuál de ellas tendría más sentido para los desarrolladores que consumn la apis y por qué? Creo que no hay reglas inamovibles cuando se trata de diseños de URL REST y convenciones de nomenclatura, pero solo quería saber qué ruta debería tomar para ayudar a los desarrolladores a comprender mejor las API.

¡Toda ayuda apreciada!

En mi experiencia, GET /users/{id} GET /users/email/{email} es el enfoque más común. También esperaría que los métodos devuelvan un 404 No encontrado si un usuario no existe con el id o email proporcionado. No me sorprendería ver GET /users/id/{id} , tampoco (aunque en mi opinión, es redundante).

Comentarios sobre los otros enfoques

  1. GET /users/id={id} GET /users/email={email}
    • No creo que haya visto esto, y si lo hubiera visto, sería muy confuso. Es casi como si estuviera tratando de imitar parámetros de consulta con parámetros de ruta.
  2. GET /users?id={id} GET /users?email={email}
    • Creo que dio en el clavo cuando mencionó el uso de parámetros de consulta para el filtrado.
    • ¿Tendría algún sentido llamar a este recurso con una id y un email (por ejemplo, GET /users?id={id}&email={email} )? Si no, no usaría un solo método de recursos como este.
    • Esperaría que este método recuperara una lista de usuarios con parámetros de consulta opcionales para el filtrado, pero no esperaría que el id , el email o cualquier identificador único se encuentre entre los parámetros. Por ejemplo: GET /users?status=BANNED podría devolver una lista de usuarios prohibidos.

Echa un vistazo a esta respuesta de una pregunta relacionada.

Si observa esto de forma pragmática, tiene una colección de usuarios:

 /users # this returns many 

Cada usuario tiene una ubicación de recursos dedicada:

 /users/{id} # this returns one 

También tiene varias formas de buscar usuarios:

 /users?email={email} /users?name=*bob* 

Como estos son todos parámetros de consulta para / usuarios, todos deberían devolver listas … incluso si es una lista de 1.

Escribí una publicación de blog sobre el diseño pragmático de RESTful API aquí que habla sobre esto, entre otras cosas, aquí: http://www.vinaysahni.com/best-practices-for-a-pragmatic-restful-api

Acerca de los recursos del usuario

en la ruta /users siempre obtendrá un recurso de colección devuelto.

en la ruta /users/[user_id] obtendrá un recurso singleton que representa al usuario con su id [user_id] o, alternativamente, una respuesta 404 si no existe ningún usuario con el [user_id] solicitado (o forbidden (401) si no está permitido para acceder al recurso de usuario solicitado, etc.). Cada ruta de recursos tiene solo un identificador único y usted usa esto para encontrar / identificar los recursos. No es posible usar varios identificadores para el mismo recurso en la misma ruta de recursos. Si obtiene un recurso devuelto en una respuesta, ese identificador se incluye en la respuesta como una HREF propia para ubicar / identificar el recurso.

Puede consultar la ruta /users con los parámetros GET / query. Esto devolverá una colección con usuarios que cumplan con los criterios solicitados. La colección que se devuelve contiene los recursos del usuario, todos con su autoidentificación HREF.

Acerca de los recursos de correo electrónico

Si miro lo que sugirió para el correo electrónico, preferiría pensar lo siguiente:

Los correos electrónicos de los usuarios también son recursos. Entonces, creo que /users/[user_id]/emails devuelve una colección de direcciones de correo electrónico para el usuario con ID user_id . /users/[user_id]/emails/[email_id] devuelve el correo electrónico del usuario con user_id y [’email_id’]. Lo que usas como identificador depende de ti, pero me quedaría con un entero. Puede eliminar un correo electrónico del usuario enviando una solicitud DELETE a la ruta que identifica el correo electrónico que desea eliminar. Entonces, por ejemplo, DELETE en /users/[user_id]/emails/[email_id] eliminará el correo electrónico con email_id que pertenece al usuario con user_id. Lo más probable es que solo ese usuario tenga permiso para realizar esta operación de eliminación. Otros usuarios obtendrán una respuesta 401.

Si un usuario puede tener solo una dirección de correo electrónico, puede atenerse a /users/[user_id]/email Esto devuelve un recurso singleton. El usuario puede actualizar su dirección de correo electrónico PONIENDO o POST una nueva dirección de correo electrónico en esa url. Si en su aplicación no permite usuarios sin un correo electrónico, debe responder con un 401 si envía una solicitud DELETE a esa url.