Kilka porad na temat usług REST

O usługach REST, które dzisiaj są wszechobecne pisałem już wiele razy np. tutaj.  Dzisiaj chciałbym napisać krótkie podsumowanie w formie porad i antywzorców. Zaczynamy:

1. Nigdy nie używaj czasowników w URI.

Przykład błędnych linków:

GET: localhost\persons\1\UpdateEmail?email=’…’

Jedynym dozwolonym czasownikiem w adresie to HTTP verb. Całość linku to nic innego jak hierarchia zasobów. Poprawna aktualizacja adresu email może wyglądać zatem następująco:

PUT: localhost\persons\1\email

Metoda PUT oznacza, że mamy do czynienia z modyfikacją danych. UpdateEmail to nazwa metody, a nie zasobu co jest sprzeczne z REST. Adres email’a w przypadku PUT można umieścić w ciele zapytania.

Analogicznie jeśli chcemy odczytać dane osoby, nie powinniśmy:

GET localhost\persons\1\getdata

Poprawny adres to:

GET localhost\persons\1\data

2. REST != RPC.  

Osoby zaczynające z REST, często próbują korzystać z tego typu usług tak samo jak np. z WCF. Klasyczne RPC (Remote-Procedure-Call) polega na wykonaniu konkretnej metody na usłudze. REST to hierarchia zasobów  więc powinniśmy tworzyć linki w postaci:

localhost/persons/1/address/town

Widzimy, że operujemy tutaj na kilku poziomach. Niepoprawną z kolei postacią jest:

localhost/persons/gettown?id=1

Wynika to nie tylko z użycia czasownika w nazwie, ale również w operowaniu bezpośrednio na korzeniu zasobów, zamiast na wykorzystaniu całej dostępnej hierarchii.

3. Korzystaj z dostępnych metod  HTTP.

Jeśli chcemy usunąć zasób wtedy:

DELETE local/host/persons/1

Początkujące osoby zbyt często korzystają wyłącznie z GET. Jeśli usługa ma realizować zadania CRUD, wtedy zdecydowanie potrzebujemy POST,GET,PUT,DELETE.

4. Korzystaj z dostępnych statusów HTTP.

Status 200 (OK) zdecydowanie nie jest jedynym z którego możemy korzystać. Jeśli operacja nie uda się, wtedy oprócz zwrócenia błędu w ciele HTTP, należy zwrócić również kod np. 500 (Internal Error) albo 400 (Bad Request) w zależności od kontekstu. Kody od 400 to błędy spowodowane przez klienta (np. nieprawidłowe zapytanie), z kolei od 500 to błędy spowodowane przez serwer.

Jeśli tworzymy nową encję za pomocą HTTP POST, można zwrócić 201 (Created) zamiast po prostu 200 (OK), który bardziej nadaję się na zapytania HTTP GET.

Inny przykład to kod 404 (Not found). Jeśli użytkownik wywoła localhost/persons/5, a osoba o identyfikatorze 5 nie istnieje, wtedy zamiast 200 należy zwrócić kod 404 .

5. QueryString

Klasyczne parametry QueyString wciąż są dozwolone, ale nie powinny określać one zasobów. Innymi słowy, złą praktyką jest:

localhost/persons?id=1

Identyfikator w tym przypadku jest ściśle powiązany z zasobem. Dopuszczalne jest za to używanie QueryString do określenia np. sortowania:

lcoalhost/persons?sort=desc

Podobnie sprawa wygląda z filtrowaniem czy z innymi parametrami, które nie określają zasobów a po prostu np. ich sposób wyświetlania.

6. Zwrócenie stanu obiektu po aktualizacji.

Utworzenie zasobu lub jego aktualizacja (POST, PUT) powinny zwracać jego reprezentacje albo link, który umożliwia odczytanie pełnego stanu. Innymi słowy, po utworzeniu zasobu, ciało odpowiedzi nie może być puste. Zwykle zwraca się mapę linków\operacji, które można wykonać na nowo utworzonym zasobie.

7.  Usługa powinna być bezstanowa.

Umożliwia to łatwiejsze skalowanie jak i cachowanie. Oznacza to, że wywołanie danej akcji, nie powinno zależeć od wykonania wcześniejszych operacji. Oczywiście mowa o stanie usługi, a nie aplikacji, gdzie stan stanowi zestaw reguł biznesowych. Z tego względu, autoryzacja nie powinna bazować na ciasteczkach czy sesjach ponieważ łamią one tą zasadę. Lepiej przesyłać dany token w każdym zapytaniu. Innymi słowy, każde zapytanie powinno dostarczyć wszystkie niezbędne dane do wykonania akcji.