Jestem w trakcie tworzenia interfejsu API REST i obecnie napotykam następujący problem:
Foo
jest pierwszym zasobem. Operacje CRUD można zastosować za pomocą/foo/
identyfikatora URI.Bar
jest drugim zasobem. Operacje CRUD można zastosować za pomocą/bar/
identyfikatora URI.- Każdy
Foo
jest powiązany z zerem lub jednymBar
. Powodem, dla którego nie traktuję tegoBar
jako podrzędnego źródła,Foo
jest to, że ta samaBar
instancja może być współużytkowana przez wiele różnychFoo
. Pomyślałem, że lepiej jest uzyskać do niego dostęp za pośrednictwem niezależnego identyfikatora URI zamiast/foo/[id]/bar
.
Mój problem polega na tym, że w znacznej liczbie przypadków klienci, którzy pytają o Foo
instancję, są również zainteresowani powiązaną Bar
instancją. Obecnie oznacza to, że muszą wykonać dwa zapytania zamiast jednego. Chcę wprowadzić sposób, który pozwala uzyskać oba obiekty za pomocą jednego zapytania, ale nie wiem, jak modelować interfejs API w tym celu. Co do tej pory wymyśliłem:
- Mogłem wprowadzić parametr zapytania podobnego do tego:
/foo/[id]?include_bar=true
. Problem z tym podejściem polega na tym, że reprezentacja zasobów (np. Struktura JSON) odpowiedzi musiałaby wyglądać inaczej (np. Kontener taki jak{ foo: ..., bar: ... }
zamiast tylko serializacjiFoo
), co powoduje, żeFoo
punkt końcowy zasobu jest „heterogeniczny”. Nie sądzę, że to dobra rzecz. Podczas wysyłania zapytań/foo
klienci powinni zawsze uzyskać tę samą reprezentację zasobów (strukturę), niezależnie od parametrów zapytania. - Innym pomysłem jest wprowadzenie nowego punktu końcowego tylko do odczytu, np
/fooandbar/[foo-id]
. W takim przypadku nie ma problemu ze zwróceniem takiej reprezentacji{ foo: ..., bar: ... }
, ponieważ wtedy jest to tylko „oficjalna” reprezentacjafooandbar
zasobu. Jednak nie wiem, czy taki punkt końcowy pomocnika jest naprawdę ODPOCZYNYWNY (dlatego napisałem „może” w tytule pytania. Oczywiście jest to technicznie możliwe, ale nie wiem, czy to dobry pomysł).
Co myślisz? Czy są jakieś inne możliwości?
Bar
może istnieć bez powiązania zFoo
. Jednak, jak napisałem powyżej, możliwe jest, że wieleFoo
s dzieli to samoBar
. Powinno być możliwe stworzenieFoo
bezBar
skojarzenia, więc nie sądzę, żeBar
powinienem być traktowany jak rodzic.Odpowiedzi:
Poziom 3 REST API wrócą ci
Foo
, a także odnośnik wskazujący związaneBar
.Następnie możesz dodać funkcję API do drążenia w dół, która umożliwia nawigację po linkach;
Funkcja drążenia w dół byłaby umieszczona przed interfejsami API i przechwytywała odpowiedzi. Wykonałby drążenie w dół połączeń i uzupełniał dane przed odesłaniem odpowiedzi dzwoniącemu.
Jest to dość powszechna rzecz na REST poziomu 3, ponieważ znacznie zmniejsza dyskontowanie klientów / serwerów w porównaniu z wolnym HTTP. Firma, dla której pracuję, tworzy interfejs API REST poziomu 3 z dokładnie tą funkcją.
Aktualizacja: Jaka jest jego wartość, oto jak może wyglądać w JSON. W ten sposób nasz interfejs API miałby taką strukturę. Pamiętaj, że możesz zagnieżdżać swoje wiercenia, aby wyciągać linki z linków itp.
źródło
links
tablicę, każdy wpis jest obiektem związek zrel
iuri
pole (podobny do przykładu xml). Czy powinienem po prostu dodać trzecie pole do każdego obiektu łącza (np.data
)? Czy jest jakiś standard?W przypadku 95% wszystkich zapytań chcą
Foo
jak równieżBar
, po prostu zwrócić go wewnątrz tegoFoo
obiektu podczas żądaniaFoo
. Po prostu dodaj właściwośćbar
(lub inny termin dla relacji) i umieśćBar
tam obiekt. Jeśli relacja nie istnieje, użyj wartości null.Myślę, że to przesadzasz :)
źródło
Foo
, a ponieważ każda z nichBar
ma dość dużą pamięć (około 3x-4x wielkościFoo
), nie chcę zwracać,Bar
jeśli klient nie zażąda jej wprost.