2014-11-11 12 views
5

Mam proste API, które działa tak:relaksującego sposób, aby zaakceptować wybór

  1. Użytkownik tworzy żądanie (POST /requests)
  2. Inny użytkownik pobiera wszystkie żądania (GET /requests)
  3. Następnie dodaje oferta na żądanie (POST /requests/123/offers)
  4. Original użytkownik może teraz zobaczyć wszystkie oferty są wykonane na zamówienie (GET /requests/123/offers)

Co chcę zrobić, to pozwolić użytkownikowi na zaakceptowanie prośby, ale nie mogę wymyślić najlepszego sposobu, aby to zrobić REST.

Czy powinienem to zrobić z czasownikiem PATCH? Podobnie jak PATCH /requests/123 i wymagają, aby ciało poprawki zawierało prawidłowy identyfikator oferty?

+0

Powiedziałbym, że POST byłby odpowiedni do zaakceptowania wniosku, można użyć PUT do tworzenia żądań i ofert. – Shriike

Odpowiedz

7

Przyjęcie oferty pięć razy powinno mieć taki sam skutek, jak jej przyjęcie raz. Jest idempotentny. Więc powinien to być PUT.

Być może warto rozważyć wybór innej nazwy dla "żądań". Kiedy wykonuję GET /requests/123, proszę o odpowiedź, która jest żądaniem? Może to być trochę dezorientujące dla klientów.

Ponadto staraj się unikać zagnieżdżania identyfikatorów zasobów. To może przysporzyć Ci później problemów. Oferta tak naprawdę nie musi być "pod" odpowiednią prośbą. Co się dzieje, gdy później chcesz mieć oferty odpowiadające wielu prośbom?

Dobrą zasadą jest, jeśli uważają Państwo za „Gizmo” podmiot w entity-relationship model, powinien to być poziom root-URI, jak w GET /gizmos/17, nie GET /widgets/54/gizmos/17. Częstym błędem jest stwierdzenie "Każdy Gizmo ma dokładnie jeden powiązany widget, więc powinienem zagnieździć identyfikatory URI Gizmo jako rozszerzenia identyfikatorów URI widgetów."

Poniżej mam sugestię, jak będą wyglądały operacje. Zamiast tego możesz zastąpić niektóre odniesienia identyfikatorów identyfikatorami URI, ale to zależy od Ciebie.

POST /requests   ---> 201 Created 
           Location: /requests/123 

GET /requests    ---> 200 OK 
           [ 
            { 
             "requestId": 123, 
             "offersUri": "/offers?requestId=123", 
             ... 
            }, 
            ... 
           ] 

POST /offers    ---> 201 Created 
{        Location: /offers/456 
    "requestId": 123, 
    "amount": 300, 
    ... 
} 

GET /offers?requestId=123 ---> 200 OK 
           [ 
            { 
             "requestId": 123, 
             "amount": 300, 
             ... 
            } 
           ] 

PUT /offers/456/approval ---> 204 No Content 
PUT /offers/456/approval ---> 204 No Content 
PUT /offers/456/approval ---> 204 No Content 
+1

Dziękujemy za podanie głęboko zagnieżdżonych identyfikatorów. Jest to zbyt częsty błąd, gdy ludzie są początkującymi architektami REST. –

+0

Dzięki! Twoja odpowiedź wydaje się być właściwą drogą. Mam tylko jedno pytanie dotyczące listy ofert. W jaki sposób chciałbym zapewnić łatwy sposób na odzyskanie wszystkich ofert na żądanie? Czy powinien istnieć parametr url do filtrowania w 'GET/offers? Request = 123' czy powinienem podać parametr do osadzenia tych danych w żądaniu' GET/request/123? Embedded = true', który zastąpiłby ofert z faktycznymi ofertami ? –

+1

@JanisPeisenieks 'GET/offers? RequestId = 123' wydaje mi się sensowne. Unikaj ostatniej sugestii, 'GET/request/123? Embedded = true'. Zasób powinien łączyć się z powiązanymi zasobami - nie osadzać ich. W rzeczywistości możesz nawet pomyśleć o tym, aby zasób żądania wyglądał tak, zamiast tego, co zasugerowałem powyżej: '{" requestId ": 123," offersUri ":"/offers? RequestId = 123 "}' –

1

W zależności od charakteru akceptacji.

Jeśli Akceptacja jest prostym atrybutem oferty, OPCJĘ oferty z ustawieniem Akceptacja na wartość True.

Jeśli Akceptacja jest bardziej złożona, a zatem stanowi samodzielny zasób, WARTO wyrazić zgodę na ofertę (PUT /requests/123/offers/acceptance).

Jeśli istnieje coś takiego jak odrzucenie lub prośba o wyjaśnienie oferty, mogę uznać odpowiedni zasób za odpowiedź, a nie za akceptację, oraz za PUT (put /requests/123/offers/response).

+0

Nie zasługuję na zgubę, ale wydaje się, że umieszczasz wiele danych akcji w URI, co narusza zasadę identyfikacji i transformacji REST. –

+0

Nie widzę, jak traktowanie odpowiedzi jako oddzielnego dokumentu lub zasobu stanowi działanie kodujące do identyfikatora URI.Oferowane przeze mnie opcje (w przypadku, gdy odpowiedź jest modelowana jako obiekt złożony) to Akceptacja i Odpowiedź, a nie * Akceptuj * i * Odpowiedz * (które mogą być mylące z działaniem). W rzeczywistości w formalnym systemie RFQ jest całkowicie możliwe, że odpowiedź powinna być modelowana osobno. –

+0

Sądzę, że widzę REST jako połączenie zasobów i reprezentacji, a twój model wydaje się używać zasobów. Jeśli stan oferty (przyjęty/odrzucony) nie jest reprezentacją, nie wiem, co to jest. –

Powiązane problemy