Jak skonstruować REST API, które pobiera tablicę identyfikatorów dla zasobów

103

Buduję REST API dla mojego projektu. API do pobierania INFO danego użytkownika to:

api.com/users/[USER-ID]

Chciałbym również umożliwić klientowi przekazanie listy identyfikatorów użytkowników. Jak mogę zbudować interfejs API, aby był zgodny ze specyfikacją REST i przyjmował listę identyfikatorów użytkowników?

uclajatt
źródło
Najbardziej ogólną odpowiedź podaje @Shuja, ponieważ inne odpowiedzi od listonosza nie działały i są zależne od zaplecza bazy danych. Możesz jednak mieć punkt końcowy interfejsu API, aby zażądać wielu identyfikatorów.
Eswar

Odpowiedzi:

97

Jeśli przekazujesz wszystkie parametry w adresie URL, prawdopodobnie najlepszym wyborem będą wartości oddzielone przecinkami. Wtedy miałbyś szablon adresu URL podobny do następującego:

api.com/users?id=id1,id2,id3,id4,id5
Florin Dumitrescu
źródło
7
@uclajatt, REST to model architektoniczny, a nie protokół, a jeśli przestudiujesz główne dostępne obecnie interfejsy API REST, zobaczysz, że istnieje wiele sposobów ich implementacji. Podejście, które proponuję, jest prawdopodobnie jednym z najbardziej zbliżonych do tej koncepcji, ponieważ spełnia wszystkie opisane tutaj ograniczenia: en.wikipedia.org/wiki/… . Możesz używać CSV tylko do reprezentowania tablic w żądaniach, podczas gdy odpowiedzi usługi powinny być serializowane przy użyciu XML lub JSON. Czy są jakieś szczególne powody, dla których nie uważacie mojego podejścia za REST?
Florin Dumitrescu
10
Dlaczego nie to? api.com/users?id=id1&id=id2&id=id3&id=id4&id=id5
senfo
7
@senfo, wolę id = id1, id2, id3, ponieważ sprawia, że ​​URI jest krótszy i łatwiejszy do odczytania (na przykład przez człowieka podczas operacji debugowania). Indywidualne parametry dla każdej wartości sprawiłyby, że identyfikator URI byłby szczególnie trudny do śledzenia, gdyby między identyfikatorami znajdowały się inne parametry: api.com/users?id=id1&id=id2&joined-after=2013-01-01&id=id3
Florin Dumitrescu
12
Jednak większość serwerów WWW obsługuje adresy URL o długości około 2000 bajtów. Jak sprawić, by moje API obsługiwało do 5000 identyfikatorów?
nicky_zs
6
@senfo W przypadku adresów URL, takich jak …?id=1&id=2&id=3, nie ma gwarancji, że zduplikowane parametry zapytania zostaną połączone w tablicę. Z powyższym ciągiem zapytania PHP zdarza się powiedzieć, że idrówna się [1, 2, 3], ale Ruby on Rails mówi, że to równa się 3, a inne frameworki mogą również działać inaczej, np. Mówiąc, że idrówna się 1. …?id=1,2,3Takie adresy URL pozwalają uniknąć tego potencjalnego pomyłki.
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

IMO, powyższe wywołania nie wyglądają na RESTful, jednak są to szybkie i wydajne obejście (y). Jednak długość adresu URL jest ograniczona przez serwer WWW, np . Tomcat .

RESTful próba:

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

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

Serwer odpowie na URI nowo utworzonego zasobu zadania wsadowego .

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

Teraz klient może pobrać odpowiedź wsadową lub postęp zadania przez odpytywanie

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


Oto jak inni próbowali rozwiązać ten problem:

Nilesh
źródło
7
Żądanie POST w celu uzyskania wielu wyników nie jest pełne. Twój przykład pokazuje tworzenie zasobu, w którym można
opublikować post
2
Tworzenie tymczasowego zasobu jest RESTful, prawda? I otrzymuję zasoby za pomocą GET, ponownie RESTful.
Nilesh
tak, ale nic z tego nie było w pierwotnym pytaniu, które dotyczy tylko uzyskania informacji dla wielu identyfikatorów użytkowników
Anentropic
1
Dzięki @Anentropic za wskazanie. Ponownie przeczytałem pytanie, które zadaje. Jak zbudować REST API, które pobiera tablicę identyfikatorów dla zasobów? i zgadzam się, moja odpowiedź jest inna. Przepraszam, że nie rozumiem.
Nilesh
Podoba mi się ta odpowiedź, ponieważ RESTful sposób na pozyskanie wielu użytkowników polega na tym mechanizmie.
Shane Courtrille
20

Znalazłem inny sposób zrobienia tego samego, używając @PathParam. Oto przykładowy kod.

@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.
}

Zadzwoń do usługi, używając następującego adresu URL.

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

gdzie

http://localhost:8080/[War File Name]/[Servlet Mapping]/[Class Path]/data/xml/12,13,56,76
Shuja
źródło
5
Podoba mi się ten, ponieważ GET jest spójny. W tym przykładzie możesz użyć jednej lub wielu liczb. I tak naprawdę nie jest to wyszukiwanie (parametry), ponieważ podajesz zapleczu dokładne identyfikatory, które chcesz.
markthegrea
1
Widzę, że najbardziej pozytywna odpowiedź nie działa, a Twoja odpowiedź jest prawdopodobnie najbardziej ogólna. Powinien zostać przyjęty jako odpowiedź.
Eswar
18

O ile wolę to podejście: -

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

Właściwy sposób to

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

lub

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

Tak to robi rack . Tak to robi php . Tak też robi to node ...

Kyristopher
źródło
19
Nie jestem pewien, czy odwoływanie się do standardów PHP jako wytycznej do naśladowania jest najlepszą radą. eev.ee/blog/2012/04/09/php-a-fractal-of-bad-design
trebor
Nie tak robi to Flask.
jscul
0

Możesz zbudować Rest API lub spokojny projekt przy użyciu ASP.NET MVC i zwrócić dane jako JSON. Przykładowa funkcja kontrolera to:

        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));
        }

Następnie po prostu wywołujesz funkcję GetUsers za pośrednictwem zwykłej funkcji AJAX dostarczającej tablicę identyfikatorów (w tym przypadku używam jQuery stringify, aby wysłać tablicę jako ciąg znaków i zdematerializować ją z powrotem w kontrolerze, ale możesz po prostu wysłać tablicę int i odebrać to jako tablica int w kontrolerze). Zbudowałem cały Restful API przy użyciu ASP.NET MVC, który zwraca dane jako json międzydomenowy i może być używany z dowolnej aplikacji. Oczywiście, jeśli możesz używać 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
źródło
3
Przepraszam, nie pytałem o sposób implementacji API. Pytałem tylko, jak skonstruować identyfikator URI interfejsu API, aby klient miał dostęp do informacji o tablicy użytkowników. Mogę przekazać id poprzez parametry zapytania, ale uważam, że nie będzie to bardzo spokojne.
uclajatt
@uclajatt Dlaczego uważasz, że to nie jest RESTful?
Darrel Miller,
1
Uważam, że przekazywanie id lub innych wartości za pośrednictwem parametrów zapytania jest rzeczywiście spokojnym podejściem do interakcji z systemem. Jak zbudujesz swój Uri, to zależy od Ciebie. Czy to użytkownicy / wszyscy, użytkownicy / tablica, tablica / użytkownicy lub jakakolwiek inna konwencja nazewnictwa, którą uważasz za sensowną. Biorąc pod uwagę, jak działa framework MVC, bardzo łatwo jest go używać do budowania spokojnego API, ponieważ możesz organizować i budować Uris tak, jak ich potrzebujesz.Gdy masz swój Uris, możesz przekazać parametry za pomocą AJAX jako jednego ciągu, lub jako wiele wartości, jeśli używasz formularza i publikujesz w akcji MVC.
Vasile Laur
1
@uclajatt Już dwa razy w tym poście zostałeś zapytany, dlaczego uważasz, że przekazanie listy oddzielonej przecinkami w parametrze zapytania nie jest RESTful i nawet nie zadasz sobie trudu, aby na nie odpowiedzieć, nie mówiąc już o zaakceptowaniu któregokolwiek z tych bardzo wiarygodnych rozwiązań!? ! Nie fajnie.
samis