Muszę zaprojektować API zapytań RESTful, które zwraca zestaw obiektów na podstawie kilku filtrów. Zwykłą metodą HTTP jest to GET. Jedynym problemem jest to, że może mieć co najmniej kilkanaście filtrów, a jeśli przekażemy je wszystkie jako parametry zapytania, adres URL może być dość długi (na tyle długi, że może zostać zablokowany przez jakąś zaporę).
Zmniejszenie liczby parametrów nie wchodzi w grę.
Jedną z alternatyw, o których mógłbym pomyśleć, jest użycie metody POST w identyfikatorze URI i wysłanie filtrów jako części treści POST. Czy to przeciwko byciu RESTfull (Wykonywanie wywołania POST w celu zapytania o dane).
Czy ktoś ma lepsze sugestie dotyczące projektu?
api
rest
http-parameters
misjaE46
źródło
źródło
Odpowiedzi:
Pamiętaj, że w przypadku REST API wszystko zależy od Twojego punktu widzenia.
Dwie kluczowe koncepcje interfejsu API REST to punkty końcowe i zasoby (jednostki). Mówiąc luźno, punkt końcowy zwraca zasoby za pośrednictwem GET lub akceptuje zasoby za pośrednictwem POST i PUT i tak dalej (lub kombinacja powyższych).
Przyjmuje się, że w przypadku POST wysyłane dane mogą, ale nie muszą, skutkować utworzeniem nowego zasobu i skojarzonego z nim punktu (-ów) końcowego (-ych), który najprawdopodobniej nie będzie „żył” pod opublikowanym adresem URL. Innymi słowy, kiedy POST wysyłasz dane gdzieś do obsługi. Punkt końcowy POST nie znajduje się tam, gdzie normalnie można znaleźć zasób.
Cytowanie z RFC 2616 (z pominięciem nieistotnych części i podświetleniem odpowiednich części):
Przyzwyczailiśmy się do punktów końcowych i zasobów reprezentujących „rzeczy” lub „dane”, czy to użytkownika, wiadomość, czy książkę - niezależnie od tego, na czym polega problem. Jednak punkt końcowy może również ujawniać inny zasób - na przykład wyniki wyszukiwania.
Rozważmy następujący przykład:
To jest typowy REST CRUD. A co by było, gdybyśmy dodali:
W tym punkcie końcowym nie ma nic nie-REST. Przyjmuje dane (podmiot) w postaci treści żądania. Te dane to kryteria wyszukiwania - DTO jak każde inne. Ten punkt końcowy tworzy zasób (jednostkę) w odpowiedzi na żądanie: Wyniki wyszukiwania . Zasób wyników wyszukiwania jest zasobem tymczasowym, udostępnianym klientowi natychmiast, bez przekierowania i bez ujawniania się z innego kanonicznego adresu URL.
Nadal jest REST, z wyjątkiem tego, że encje nie są książkami - encja żądania to kryteria wyszukiwania książek, a encja odpowiedzi to wyniki wyszukiwania książek.
źródło
BooksSearchCriteriaDTO
iBooksSearchResultsDTO
.POST
jest używany do części C CRUD. Wybrałbym zwykłe stare 200, opcjonalnie może 204 dla pustych wyników wyszukiwania.Wiele osób zaakceptowało praktykę, że GET ze zbyt długim lub zbyt złożonym ciągiem zapytania (np. Ciągi zapytań nie obsługują łatwo zagnieżdżonych danych) można zamiast tego wysłać jako POST, ze złożonymi / długimi danymi reprezentowanymi w treści wniosku.
Wyszukaj specyfikację POST w specyfikacji HTTP. Jest niesamowicie szeroki. (Jeśli chcesz przepłynąć pancernikiem przez lukę w REST ... użyj POST.)
Tracisz niektóre korzyści płynące z semantyki GET ... takie jak automatyczne ponawianie próby, ponieważ GET jest idempotentny, ale jeśli możesz z tym żyć, łatwiej będzie zaakceptować przetwarzanie naprawdę długich lub skomplikowanych zapytań za pomocą POST.
(lol długa dygresja ... Niedawno odkryłem, że zgodnie ze specyfikacją HTTP GET może zawierać treść dokumentu. Jest jedna sekcja, która mówi parafrazując: „Każde żądanie może mieć treść dokumentu oprócz tych wymienionych w tej sekcji” ... a sekcja, do której się odnosi, nie zawiera żadnego. Przeszukałem i znalazłem wątek, w którym autorzy HTTP rozmawiali o tym, i było to zamierzone, aby routery i inne nie musiały rozróżniać różnych wiadomości. ćwiczyć wiele elementów infrastruktury, co powoduje upuszczenie treści GET. Możesz więc GET z filtrami reprezentowanymi w treści, np. POST, ale będziesz rzucał kostką).
źródło
W skrócie: utwórz POST, ale zastąp metodę HTTP za pomocą nagłówka X-HTTP-Method-Override .
Prawdziwa prośba
POST / książki
Jednostka podmiotu
{"title": "Ipsum", "year": 2017}
Nagłówki
X-HTTP-Method-Override: GET
Po stronie serwera sprawdź, czy istnieje nagłówek X-HTTP-Method-Override, a następnie przyjmij jego wartość jako metodę tworzenia trasy do końcowego punktu końcowego w zapleczu. Weź również treść jednostki jako ciąg zapytania. Z punktu widzenia zaplecza żądanie stało się po prostu prostym GET.
W ten sposób projekt pozostaje w harmonii z zasadami REST.
Edycja: Wiem, że to rozwiązanie było pierwotnie przeznaczone do rozwiązania problemu czasownika PATCH w niektórych przeglądarkach i serwerach, ale działa również dla mnie z czasownikiem GET w przypadku bardzo długiego adresu URL, który jest problemem opisanym w pytaniu.
źródło
X-
usunięcia i 1.5. nie zastępuje istniejących specyfikacji. ...X-
czy IMO pozostanie tutaj.Jeśli programujesz w Javie i JAX-RS, polecam używanie @QueryParam z @GET
Miałem to samo pytanie, kiedy musiałem przejrzeć listę.
Zobacz przykład:
Wzorzec URI: „poc / test? Code = 1 & code = 2 & code = 3
@QueryParam automatycznie skonwertuje parametr zapytania „orderBy = age & orderBy = name” na java.util.List.
źródło