Cómo construir una API REST que tome una matriz de identificadores para los recursos

103

Estoy construyendo una API REST para mi proyecto. La API para obtener la INFORMACIÓN de un usuario determinado es:

api.com/users/[USER-ID]

También me gustaría permitir que el cliente pase una lista de ID de usuario. ¿Cómo puedo construir la API para que sea RESTful y tenga una lista de ID de usuario?

uclajatt
fuente
La respuesta más genérica la da @Shuja, porque otras respuestas del cartero no funcionaron y dependen del backend de la base de datos. Sin embargo, puede tener un punto final de API para solicitar múltiples ID.
Eswar

Respuestas:

97

Si está pasando todos sus parámetros en la URL, probablemente los valores separados por comas serían la mejor opción. Entonces tendrías una plantilla de URL como la siguiente:

api.com/users?id=id1,id2,id3,id4,id5
Florin Dumitrescu
fuente
7
@uclajatt, REST es un modelo arquitectónico y no un protocolo, y si estudia las principales API REST disponibles en la actualidad, verá que hay múltiples formas de implementarlo. El enfoque que sugiero es probablemente uno de los más cercanos al concepto, ya que cumple con todas las limitaciones descritas aquí: en.wikipedia.org/wiki/… . Solo usaría CSV para representar matrices en solicitudes, mientras que las respuestas de servicio deben serializarse usando XML o JSON. ¿Hay alguna razón en particular por la que no considere que mi enfoque sea DESCANSO?
Florin Dumitrescu
10
¿Por qué no esto? api.com/users?id=id1&id=id2&id=id3&id=id4&id=id5
senfo
7
@senfo, prefiero id = id1, id2, id3 porque hace que el URI sea más corto y más fácil de leer (por un humano, durante una operación de depuración, por ejemplo). Los parámetros individuales para cada valor harían que el URI sea especialmente más difícil de seguir si hay otros parámetros entre los identificadores: api.com/users?id=id1&id=id2&joined-after=2013-01-01&id=id3
Florin Dumitrescu
12
Sin embargo, la mayoría de los servidores web admiten una longitud de URL de aproximadamente 2000 bytes. ¿Cómo hacer que mi API admita hasta 5,000 ID?
nicky_zs
6
@senfo En URL como …?id=1&id=2&id=3, no hay garantía de que los parámetros de consulta duplicados se combinen en una matriz. Con la cadena de consulta anterior, PHP le dice que ides igual [1, 2, 3], pero Ruby on Rails le dice que es igual 3, y otros marcos también pueden actuar de manera diferente, por ejemplo, diciendo idigual 1. Las URL como …?id=1,2,3evitan este potencial de confusión.
Rory O'Kane
33
 api.com/users?id=id1,id2,id3,id4,id5
 api.com/users?ids[]=id1&ids[]=id2&ids[]=id3&ids[]=id4&ids[]=id5

En mi opinión, las llamadas anteriores no parecen RESTful, sin embargo, estas son una solución rápida y eficiente (y). Pero la longitud de la URL está limitada por el servidor web, por ejemplo, tomcat .

Intento de reposo:

POST http://example.com/api/batchtask

   [
    {
      method : "GET",
      headers : [..],
      url : "/users/id1"
    },
    {
      method : "GET",
      headers : [..],
      url : "/users/id2"
    }
   ]

El servidor responderá el URI del recurso por lotes recién creado .

201 Created
Location: "http://example.com/api/batchtask/1254"

Ahora el cliente puede obtener la respuesta por lotes o el progreso de la tarea mediante sondeo

GET http://example.com/api/batchtask/1254


Así es como otros intentaron resolver este problema:

Nilesh
fuente
7
La solicitud POST para obtener varios resultados no es RESTful. Su ejemplo muestra la creación de un recurso, donde es apropiado POST, pero ese es un caso totalmente diferente a la pregunta original
Anentropic
2
La creación de un recurso temporal es RESTful, ¿no? Y estoy obteniendo recursos usando GET, nuevamente es RESTful.
Nilesh
sí, pero nada de eso estaba en la pregunta original, que solo pregunta sobre cómo obtener información para múltiples identificadores de usuario
Anentropic
1
Gracias @Anentropic por señalarlo. Leí la pregunta nuevamente, pregunta ¿Cómo construir una API REST que tome una matriz de identificadores para los recursos? y estoy de acuerdo, mi respuesta es diferente. Perdón por no entender tu punto.
Nilesh
Me gusta esta respuesta ya que la forma RESTful de obtener múltiples usuarios es a través de este mecanismo.
Shane Courtrille
20

Encuentro otra forma de hacer lo mismo usando @PathParam. Aquí está el ejemplo de código.

@GET
@Path("data/xml/{Ids}")
@Produces("application/xml")
public Object getData(@PathParam("zrssIds") String Ids)
{
  System.out.println("zrssIds = " + Ids);
  //Here you need to use String tokenizer to make the array from the string.
}

Llame al servicio utilizando la siguiente URL.

http://localhost:8080/MyServices/resources/cm/data/xml/12,13,56,76

dónde

http://localhost:8080/[War File Name]/[Servlet Mapping]/[Class Path]/data/xml/12,13,56,76
Shuja
fuente
5
Me gusta este porque el GET es consistente. Puede utilizar un número o varios en este ejemplo. Y no es realmente una búsqueda (parámetros), ya que le está dando al back-end los identificadores exactos que desea.
markthegrea
1
Veo que la respuesta más votada no funciona y tu respuesta es probablemente la más genérica. Debe aceptarse como respuesta.
Eswar
18

Por mucho que prefiera este enfoque: -

    api.com/users?id=id1,id2,id3,id4,id5

La forma correcta es

    api.com/users?ids[]=id1&ids[]=id2&ids[]=id3&ids[]=id4&ids[]=id5

o

    api.com/users?ids=id1&ids=id2&ids=id3&ids=id4&ids=id5

Así es como lo hace rack . Así es como lo hace php . Así es como el nodo también lo hace ...

Kyristopher
fuente
19
No estoy seguro de que hacer referencia a los estándares PHP como una guía a seguir sea el mejor consejo. eev.ee/blog/2012/04/09/php-a-fractal-of-bad-design
trebor
Flask no lo hace así.
jscul
0

Puede crear una API Rest o un proyecto relajante utilizando ASP.NET MVC y devolver datos como JSON. Una función de controlador de ejemplo sería:

        public JsonpResult GetUsers(string userIds)
        {
           var values = JsonConvert.DeserializeObject<List<int>>(userIds);

            var users = _userRepository.GetAllUsersByIds(userIds);

            var collection = users.Select(user => new { id = user.Id, fullname = user.FirstName +" "+ user.LastName });
            var result = new { users = collection };

            return this.Jsonp(result);
        }
        public IQueryable<User> GetAllUsersByIds(List<int> ids)
        {
            return _db.Users.Where(c=> ids.Contains(c.Id));
        }

Luego, simplemente llame a la función GetUsers a través de una función AJAX regular que proporciona la matriz de ID (en este caso, estoy usando jQuery stringify para enviar la matriz como una cadena y desmaterializarla de nuevo en el controlador, pero puede enviar la matriz de entradas y recibir como una matriz de int en el controlador). Construí una API Restful completa usando ASP.NET MVC que devuelve los datos como json de dominio cruzado y que se puede usar desde cualquier aplicación. Eso, por supuesto, si puede usar ASP.NET MVC.

function GetUsers()
    {
           var link = '<%= ResolveUrl("~")%>users?callback=?';
           var userIds = [];
            $('#multiselect :selected').each(function (i, selected) {
                userIds[i] = $(selected).val();
            });

            $.ajax({
                url: link,
                traditional: true,
                data: { 'userIds': JSON.stringify(userIds) },
                dataType: "jsonp",
                jsonpCallback: "refreshUsers"
            });
    }
Vasile Laur
fuente
3
Lo siento, no estaba preguntando cómo implementar la API. Solo estaba preguntando cómo construir el URI de la API para que el cliente pueda acceder a información sobre una variedad de usuarios. Puedo pasar identificaciones a través de parámetros de consulta, pero creo que eso no será muy relajante.
uclajatt
@uclajatt ¿Por qué crees que no es RESTful?
Darrel Miller
1
Creo que pasar id's o cualquier otro valor a través de parámetros de consulta es de hecho un enfoque relajante para interactuar con un sistema. La forma en que construyas tu Uri depende de ti. Ya sea usuarios / todos, usuarios / matriz, matriz / usuarios o cualquier otra convención de nomenclatura que crea que tiene sentido. Teniendo en cuenta cómo funciona el marco MVC, es muy fácil de usar para construir una API relajante, ya que puede organizar y construir su Uris tal como lo necesita.Una vez que tenga su Uris, puede pasar sus parámetros usando AJAX como una cadena, o como valores múltiples si está usando un formulario y haciendo una publicación en una acción MVC.
Vasile Laur
1
@uclajatt Eso es dos veces ahora que te han preguntado en esta publicación por qué crees que pasar una lista separada por comas en un parámetro de consulta no es RESTful y ni siquiera te molestas en responderlo, y mucho menos aceptar cualquiera de estas soluciones tan plausibles. ! No es genial.
samis