Mam dwa zasoby: użytkowników i linki.
Użytkownicy mogą mieć kilka linków powiązanych z nimi. Zaprojektowałem mój interfejs API RESTful, abyś mógł uzyskać dostęp do linków powiązanych z użytkownikiem o następującym identyfikatorze URI:
/users/:id/links
Jednak zawsze muszę mieć identyfikator URI dla samych łączy - czasami mogę chcieć wszystkich łączy, niezależnie od użytkownika.
Do tego mam:
/links
Czy to brzmi dobrze? Masz dwa identyfikatory URI dla łączy?
Zastanawiam się, czy zamiast tego powinienem dotrzeć do linków użytkownika z identyfikatorem URI, takiego jak:
/links/user/:id
lub /links/?user=:id
W ten sposób mam tylko jeden zasób dla linków.
api
rest
api-design
Oliver Joseph Ash
źródło
źródło
/links/user/:id
/users/:id/links
) lub metody ciągu zapytania (/links/?user=:id
), ponieważ w rzeczywistości jest zapytaniem./links/user/:id
może wyglądać ładnie i / lub być łatwiejszy w routingu w niektórych ramach, ale w rzeczywistości jest to dość mylące.Odpowiedzi:
Nie, nie ma nic złego w posiadaniu wielu zasobów dla tej samej „rzeczy”, w tym przypadku list łączy.
Ostatnio zmagaliśmy się z tym samym problemem. Naszą decyzją było posiadanie wszystkich zasobów, w których nie ma ścisłej własności, których nie można zagnieżdżać. Innymi słowy, linki będą modelowane pod
Następnie filtry w kolekcji łączy są wyrażane jako parametry zapytania. Aby uzyskać linki do określonego użytkownika, użyj:
Pozwala to również na łatwiejsze komponowanie filtrów:
I łatwo to zrozumieć koncepcyjnie - masz kolekcję przedmiotów i dodajesz do niej filtry.
Biorąc to pod uwagę, nie ma nic bardziej „RESTful” w tym podejściu niż jakikolwiek inny schemat nazewnictwa URI. To tylko konwencja, którą uznaliśmy za czytelną dla człowieka i łatwą do zrozumienia dla nas jako programistów. REST nie dba o to, co umieścisz w swoich identyfikatorach zasobów.
źródło
?user=users/:userid
również ciągiem zapytania; co jest nie tak z just?userid=:userid
?"/*******"
; gdzie*
są nieprzezroczyste. ale zawsze można użyć tego samego identyfikatora w odniesieniu do tego zasobu (jak w, z linkami), aby pobrać najnowszą wersję tego zasobu i tak dalej. treść tego identyfikatora jest rozumiana tylko przez serwer pochodzenia. Oznacza to również, że jeśli identyfikatory wymagają zmiany, powiedzmy/realm/:businessid/users/:id
, klient wcale się nie zmienia./users/:userid/links
i/links?userid=:userid
? W obu przypadkach identyfikatory się nie zmieniają, pobierają bieżącą wersję tego zasobu, a klient traktuje je w ten sam sposób. Nie ma w tym przypadku kanonicznego adresu URL, ponieważ nie jest to zasób, to zapytanie, więc są to tylko dwa różne typy składni zapytania. Nie mam również jasności co do tego, jak klient nie musiałby zmieniać, gdyby zmieniła się struktura adresu URL; jest to uważane za przełomową zmianę w REST, chyba że 301 jest na miejscu./links
obsługuje interfejs zapytań,/links?user=/users/123
pozwala na podejście czarnej skrzynki do identyfikatorów zasobów u klientów, które/links?userid=123
nie obsługuje. ten drugi wymaga od klienta zrozumienia, czym jest identyfikator użytkownika i jak go uzyskać, prawdopodobnie z zasobu, który uzyskał z/users/123
lub/links/456/user
. To pierwsze oznacza, że klient może używać niezmodyfikowanego identyfikatora uri; założenie, że/links/.../user
daje odpowiedź hipermedialną (powiedzmy, zLocation:
nagłówkami).Tak więc mam obawy: / users /: userid / links zwraca „links”, ALE jeśli user_id nie zostanie zidentyfikowany, to powinno zwrócić 404.
jednak
/ links? userid =: userid potencjalnie zwróci pustą listę (zasadniczo 200), co w rzeczywistości jest prawdopodobnie błędem. I całkiem możliwe.
Chociaż oba działają, zagnieżdżanie zapewnia dodatkową funkcjonalność, z której można później korzystać.
źródło