Jak zaprojektować punkty końcowe interfejsu API do publikowania obiektu potomnego i uzyskiwania wszystkich dzieci wszystkich rodziców?

12

Na przykład mam podmioty: klient, raport. Klient może mieć wiele raportów i myślę, że punkt końcowy dla jednego zarządzania raportami powinien być zagnieżdżony w następujący sposób:

/clients/{client_id}/reports/{report_id}

Jeśli chodzi o wszystkie raporty jednego klienta, oczekuje się enpoint:

/clients/{client_id}/reports

Ale jak powinien wyglądać punkt końcowy dla uzyskania wszystkich raportów wszystkich klientów, aby interfejs API był spójny i dobrze zaprojektowany.

Moje podejście:

  1. (Widziałem to w niektórych aplikacjach Google) użyj „-” zamiast tego i parsuj jako „wszystkie”:

/clients/-/reports

Utrzymuje to ten sam format punktu końcowego, ale wygląda nieco nietypowo, nie można znaleźć żadnego kodu RFC, który sugerowałby w ten sposób.

  1. Utwórz osobny punkt końcowy tylko dla wszystkich raportów:

/reports

Ale aby uzyskać raporty klienta, nadal:

/clients/{client_id}/reports

  1. Refaktoryzuj punkty końcowe, aby „klient” nie był rodzicem, ale tylko parametrem filtru:

/reports?client={client_id} - raporty jednego klienta

/reports - raporty wszystkich klientów

W przypadku dodania nowego punktu końcowego do publikowania raportu dla konkretnego klienta, może to wyglądać brzydko, ponieważ będzie to żądanie POST z parametrem w adresie URL.

Czy są jakieś inne sugestie pomysłów?

Yann
źródło
2
Możesz być zainteresowany pytaniem
Laiv

Odpowiedzi:

3

Ale jak powinien wyglądać punkt końcowy dla uzyskania wszystkich raportów wszystkich klientów, aby interfejs API był spójny i dobrze zaprojektowany.

Przede wszystkim pamiętaj, że nie ma złotych reguł modelowania interfejsów API RESTful. Wszystko, co mamy, to najlepsze praktyki i konwencje. Biorąc to pod uwagę, prawdopodobną odpowiedzią jest - jak zwykle - wybierz ten, który najlepiej spełnia twoje wymagania, aw tym przypadku ten, który najlepiej wyraża Twój model.

Więc sprawdź trzy opcje z wyrazistości.

# 1 Notacja „-”

To świetny pomysł. Pozwala nam wyrazić warunek, do reportsktórego należą wszyscyclients . Zawęża „zapytanie” do określonego zestawu raportów (tych znajdujących się w clientsgranicach).

Utrzymuje pojęcie hierarchii (przynależności) przez cały czas, więc jeśli reportsmożna je znaleźć w różnych lokalizacjach, notacja ta ma duże znaczenie. Na przykład:

  • Wszystkie raporty należące do klientów /clients/-/reports
  • Wszystkie raporty należące do działów /departments/-/reports
  • Wszystkie raporty należące do pracowników /employees/-/reports

Jednak w przypadku pobierania wszystkich dostępnych raportów w systemie zachowanie hierarchii nie zapewnia żadnej cennej przewagi nad następną opcją.

# 2 Różne identyfikatory URI

Jeśli nie musimy wyrażać granic / kontekstów / hierarchii w momencie wyszukiwania wszystkich dostępnych raportów , takie podejście wydaje mi się bardziej rozsądne.

Nowy identyfikator URI ( /reports) pozostawia również otwartą możliwość zarządzania raportami . Nie musimy jednak zapewniać pełnego wsparcia RESTful, jeśli nie uznamy tego za konieczne. Na przykład, oświadczyłeś Make a separate endpoint just for all the reports. W porządku, musisz tylko zaimplementować GETi być może niektóre filtry do wysyłania zapytań i to wszystko.

Pamiętaj, że nadal możesz to zrobić /reports?client={client_id}. Posiadanie innego identyfikatora URI dla tego samego zasobu jest w porządku. Niektóre artykuły, które przeczytałem, nazwaliby tę solidnością .

# 3 Cofnięcie hierarchii

Mam wrażenie, że to podejście nie spełnia twoich oczekiwań. Plus, myślę, że doprowadzi cię to ostatecznie do punktu początkowego.

Wnioski

Pamiętaj, że nr 1 i nr 2 nie wykluczają się wzajemnie. Możemy wdrożyć oba. Biorąc pod uwagę faktyczną sytuację i zgodnie z przesłankami PO, wdrożyłbym tylko nr 2.


1: jest to równoważne /clients/-/reportsChyba

Laiv
źródło
0

Wzorce projektowe API Google sugerują użycie „-” w tym scenariuszu.

GET /clients/-/reports

Źródło:

https://cloud.google.com/apis/design/design_patterns#list_sub-collections

wfg4
źródło
2
Daleko mi do tego, aby nie zgadzać się z wszechmocnym Google, ale myślę, że wolałbym coś takiego /client/{client_id}/report/{report_id}i/clients/report/{report_id}
Robert Harvey
2
@RobertHarvey dlaczego nie tylko /reports?
Laiv
@Laiv: Oznaczałoby to wszystkie raporty. Odśwież stronę; Dokonałem edycji ninja.
Robert Harvey
@RobertHarvey Mam na myśli, dlaczego nie 2 różne punkty końcowe /clients...i /reports.
Laiv
1
@Laiv: OK, ale to tylko nasuwa pytanie „Jakie parametry powinienem umieścić w treści żądania?”
Robert Harvey