API: moje zwierzątka

API: moje zwierzątka
XO
  • Rejestracja:ponad 4 lata
  • Ostatnio:ponad 3 lata
  • Lokalizacja:Gdańsk
  • Postów:27
1

Mam zwierzęta jako zasoby i do nich dwa endpointy:

  • pierwszy ma zwracać wszystkie zwierzęcia.
  • drugi ma zwracać wszystkie moje zwierzaki. Moje, czyli zalogowanego principala.

Mam dwa proste pytania do takiego springowego cruda, szukam inspiracji.

  1. Jakie nazwy API byście użyli do tych endpointów? /api/animals i /api/animals/me? A może /api/animals i /api/me/animals ? Albo jeszcze inaczej? Szukam jakiejś powszechnie akceptowalnej dobrej konwencji.

  2. Czy władowalibyście to do jednego AnimalController czy może podzielilibyście też na MyAnimalController? Albo - wiedząc, że jest więcej takich moich resourców, np. moje stajnie, moje weterynarze, moje .. - to czy może warto by po prostu stworzyć zbiorczy MeController? Raczej nie, bo brzmi jak dużo zależności...?

Można założyć, że mimo wszystko w serwisach jest tam jakaś logika.

XO
Nie, jakie zadanie?
p_agon
Tylko zapytalem :)
XO
Spoko :) Ale ehh widzę że ktoś już wynalazł projekt do zarządzania zwierzętami, może poszukam lepszych pomysłów
G1
  • Rejestracja:ponad 4 lata
  • Ostatnio:10 dni
  • Postów:506
1

Api/Animals i api/animals?userid=x i zostawiłbym w jednym kontrolerze

edytowany 1x, ostatnio: gswidwa1
Riddle
Administrator
  • Rejestracja:prawie 15 lat
  • Ostatnio:około godziny
  • Lokalizacja:Koszalin
  • Postów:10094
6

Jeśli strzelasz po id usera to:

  • /users/animals
  • /users/:id/animals

To czy w jednym kontrolerze czy w dwóch to jeden pies, ja bym pewnie zrobił w jednym, ale w dwóch też będzie okej. I tak puszczasz te same testy dla nich nie ważne w jakich kontrolerach są (bo masz do tego testy prawda)?

I ogólnie wystrzegaj się nazw takich jak "my" w aplikacjach. Je się łatwo wymyśla, ale na dłuższą metę potem czytasz kod i nie wiesz co to robi. Jeśli chcesz już tak nazywać kontroller to nazwij go LoggedUserAnimals, czy cokolwiek co może wyjaśnić istote zadania. Bo "my" może znaczyć różne rzeczy w różnych kontekstach, także wyświadcz sobie przysługę i wymyśl lepszą nazwę.

edytowany 2x, ostatnio: Riddle
SO
Nazywanie kontrolera "My" czy tam me "Me" rzeczywiście nie ma sensu, ale w ogólności nie widzę nic złego w endpointcie typu /users/me w kontrolerze Users.
Riddle
@some_ONE: No tak dugo jak nie masz endpointow /users/:token, gdzie :token nie moze sie rownac "me" to faktycznie nie ma w tym nic zlego.
XO
  • Rejestracja:ponad 4 lata
  • Ostatnio:ponad 3 lata
  • Lokalizacja:Gdańsk
  • Postów:27
0

Oba wyżej przykłady zakładają przekazanie id, a co jeśli przekazuje zalogowanego usera poprzez cookie (access token) ? Kontroler odbiera objekt Authentication albo coś podobnego.

JX
  • Rejestracja:około 4 lata
  • Ostatnio:około rok
  • Postów:44
0

@Xorxorxor: Możesz próbować rozpoznawać użytkownika za pomocą UserDetails i wyświetlać mu tylko stworzone przez niego elementy:

Kopiuj
@RestController
public class ItemsController {
    private final Map<String, Set<String>> items = new ConcurrentHashMap<>();

    @PostMapping("/items")
    public void addItem(@AuthenticationPrincipal UserDetails details, @RequestParam String item) {
        String username = details.getUsername();

        if (items.containsKey(username)) {
            items.get(username).add(item);
        } else {
            items.put(username, new HashSet<>(Set.of(item)));
        }
    }

    @GetMapping("/items")
    public Set<String> getItems(@AuthenticationPrincipal UserDetails details) {
        return items.getOrDefault(details.getUsername(), Set.of());
    }
}
Riddle
Administrator
  • Rejestracja:prawie 15 lat
  • Ostatnio:około godziny
  • Lokalizacja:Koszalin
  • Postów:10094
1
Xorxorxor napisał(a):

Oba wyżej przykłady zakładają przekazanie id, a co jeśli przekazuje zalogowanego usera poprzez cookie (access token) ? Kontroler odbiera objekt Authentication albo coś podobnego.

Jeśli przekazujesz access token to nie po to żeby sterować logiką, tylko do autentykacji.

Rozumiem że chcesz mieć dwa, bezparametrowe endpointy, jeden zwracający wszystkie możliwe byty (Animals), a drugi zwracający byty przypisane do zalogowanego usera?

No mógłbyś się upodobnić do rest, iż wyobrazić sobie jakbyś coś takiego trzymał gdybyś chciał serwować zasoby.

Ja bym chyba poszedł w coś takiego

  • /animals
  • /user/animals

Wygląda jakby te dwa endpointy robiły różne rzeczy zupełnie, więc nie ma sensu ich do siebie upodabniać.

edytowany 1x, ostatnio: Riddle
W0
  • Rejestracja:ponad 12 lat
  • Ostatnio:3 minuty
  • Postów:3601
2

I fala, i cząstka :)

Tj. w zależności od potrzeb możesz mieć dwa API:

  • /api/me i pochodne, np. /api/me/animals, /api/me/preferences
  • /api/animals i informację o id użytkownika, tj. '/api/animals/{id}' oraz szczególny przypadek tj. '/api/animals/me' - przy czym ten endpoint jest akceptowalny tylko i wyłącznie gdy id nie jest dowolnym stringiem

W takim jednoaplikacyjnym świecie wolę jednak opcję pierwszą, głównie ze względu na prostotę zabezpieczenia czegoś takiego (np. każdy zalogowany użytkownik ma dostęp do /api/me/*, natomiast nie każdy użytkownik ma dostęp do /api/animals/* - w przypadku drugim trzeba dorzucać za każdym razem wyjątek na te nieszczęsne /me.
W przypadku gdy API jest wystawione gdzieś na zewnątrz dla wielu różnych aplikacji wybrałbym opcję drugą - jest to jednak prostsze z punktu widzenia użytkownika API, a /api/me/... zostawił tylko i wyłącznie dla rzeczy stricte niebiznesowych.

edytowany 1x, ostatnio: wartek01
XO
  • Rejestracja:ponad 4 lata
  • Ostatnio:ponad 3 lata
  • Lokalizacja:Gdańsk
  • Postów:27
0

Poleci ktoś jakąś konkretną książkę do rest api, gdzie właśnie tego typu problemy są poruszane?

Riddle
Administrator
  • Rejestracja:prawie 15 lat
  • Ostatnio:około godziny
  • Lokalizacja:Koszalin
  • Postów:10094
0
Xorxorxor napisał(a):

Poleci ktoś jakąś konkretną książkę do rest api, gdzie właśnie tego typu problemy są poruszane?

Weź się czymś pożytecznym zajmij :D

Porusz taką sprawę jak będziesz miał apke z 30 endpointam których nie umiesz nazwać. Teraz lepiej się zajmij rozwijaniem się w programowaniu w ogóle, a nie tym jak nazwać swoje dwa endpointy.

Np napisz testy do nich albo zrób dokumentację.

XO
Ale rozumiesz, że endpointów jest więcej niż 2, ale staram się tak robić wątek żeby był krótki i prosty do zrozumienia? Chodzi o koncepty. I moim problemem w tym wątku jest jak nazwać te endpointy, a nie pisanie do nich testów czy dokumentacji albo rozwój w innym obszarze...
Charles_Ray
  • Rejestracja:około 17 lat
  • Ostatnio:około 5 godzin
  • Postów:1880
2

Generalnie to bym wyszedł od tego, kto ma tych endpointów używać, bo jeśli Twój frontend, to powinieneś zacząć od konsumenta. Wtedy zobaczyłbyś, że endpoint pt. /animals nie ma zbyt wielkiego sensu, ponieważ nie ma np. stronicowania, a za chwilę pojawi się potrzeba wyszukiwania np. po nazwie. Zacznij od konsumenta, jeśli możesz.

Jeśli projektujesz jakieś ogólne API dla świata, to możesz wzorować się np. na GitHub albo Allegro - możesz na ich stronach poczytać, jakimi zasadami kierują się projektując API. Tutaj trzeba szczególnie przestrzegać dobrych praktyk i wprowadzać zmiany w sposób przewidywalny, bo nie możesz sobie np. od tak podmienić urla czy pola.


”Engineering is easy. People are hard.” Bill Coughran
XO
Skąd wniosek, że nie ma pagingu albo filtrowania? Mam to jako query paramsy.
99xmarcin
  • Rejestracja:około 5 lat
  • Ostatnio:6 miesięcy
  • Postów:2420
0

Ja bym zrobił tak:

/api/animals
/api/users/current/animals do zwierzątek obecnego użytkownika

Jeśli chodzi o me to raczej my, me to można łyżkę podać...


Holy sh*t, with every month serenityos.org gets better & better...
Zobacz pozostałe 9 komentarzy
W0
No i dwa pierwsze są przykładem tego o czym pisałem. Już nie wspominając o tym, że masz tam kontrakt, że wszędzie można z tego me korzystać
SO
No to mamy nieporozumienie, bo Charles_Ray odpowiadał, że słabe jest /animals/me a ty twierdziłeś, że to robi się standard jak this albo self. A przykłady zooma pokazują użycie odwrotne - /me/settings, gdzie nikt nie twierdził że to jest słabe :P
W0
Ewidentnie mamy nieporozumienie bo nie rozumiem, dlaczego /me/settings przyrównujesz do /users/me/meetings i twierdzisz, że to jest podobne.
SO
Bo /me/settings i /users/me/meetings jasno mówią, że pobierasz swojego użytkownika i dalej jego zasoby. Z kolei animals/me wygląda jakbyś nazywał siebie zwierzęciem, o czym zresztą była mowa w drugim komentarzu. Tak samo w zoomie nie ma meetings/me, bo "ty" nie jesteś spotkaniem tylko /users/me/meetings bo użytkownik może posiadać przypisane spotkania.
W0
No ok, czyli trochę gadamy o różnych rzeczach. Ogólnie masz tutaj kilka wymiarów, natomiast mi chodziło o zastępowanie {userId} słówkiem "me" występującym dosyć często w przyrodzie (być może źle się wyraziłem). Jeśli chodzi o to, czy sensowne jest tworzenie endpointu /api/animals/me to de facto trzeba by było przejść do dyskusji czy jest sens tworzenia endpointu /api/animals/{userId} zamiast np, /api/animal/users/{userId} - natomiast jeśli dopuszczamy ten pierwszy byt (IMO zależy od przypadku) to opcję z /me też trzeba dopuścić

Zarejestruj się i dołącz do największej społeczności programistów w Polsce.

Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.