REST API

Co oznacza skrót API? Czym jest protokół HTTP? Jakie zasady określają styl REST?

API

API

Application Programming Interface, czyli interfejs programistyczny aplikacji jest to zbiór zasad opisujących możliwe sposoby komunikacji z daną aplikacją. Termin ten odnosi się zazwyczaj do komunikacji na linii aplikacja-aplikacja. W przypadku komunikacji użytkownik-aplikacja mówi się raczej o UI (User Interface). Program implementujący dane API powinien być w stanie przyjmować żądania i zwracać odpowiedzi w zgodne ze zdefiniowanymi zasadami. Akcje wykonywane przez program między otrzymaniem żądania a zwróceniem odpowiedzi nie są opisywane przez API i powinny być nieistotne dla konsumenta.

Określenie API jest terminem szerokim i może być używane do opisywania różnych przypadków np.

  • Komunikacji aplikacji z system operacyjnym.
  • Komunikacji aplikacji z framework-iem / biblioteką.
  • Zdalnej komunikacji między aplikacjami.

HTTP

HTTP

Szczególnym przypadkiem zdalnej komunikacji między aplikacjami jest komunikacja za pośrednictwem sieci. Można wtedy mówić o Web API. Popularnym protokołem w komunikacji sieciowej jest HTTP, czyli Hypertext Transfer Protocol. Definiuje on zbiór zasad dotyczących komunikacji za pośrednictwem sieci. Protokół HTTP określa sposób przesyłania żądań i odpowiedzi.

Metody HTTP

Wśród zdefiniowanych w ramach protokołu HTTP metod żądań znajdują się czasowniki:

  • GET
  • HEAD
  • POST
  • PUT
  • DELETE
  • CONNECT
  • OPTIONS
  • TRACE
  • PATCH

W zależności od wybranej metody żądanie może zawierać dodatkowe informacje w przesyłanym ciele (body), to samo tyczy się odpowiedzi. Metody wykorzystywane w celu pobierania informacji (GET, HEAD, POST) mogą pozwalać na wykorzystywanie mechanizmu cache, umożliwiającego przechowywane po stronie klienta odpowiedzi i używanie ich w celu obsługi przyszłych żądań bez udziału serwera API.

Dodatkowo metody HTTP można rozróżnić ze względu na bycie bezpiecznymi i idempotentnymi.

Metody bezpieczne protokołu HTTP to takie, które z założenia nie powinny wprowadzać zmian na serwerze. Odnosi się to głównie do modyfikowania stanu zasobu, do którego odwołuje się dana metoda. Akcje takie jak na przykład tworzenie logów nie oznaczają, że zapytanie nie jest bezpieczne. Należy jednak pamiętać, że jest to jedynie zalecenie, które powinno być zaimplementowane po stronie serwera, a nie cecha protokołu HTTP. Ostatecznie nic nie stoi na przeszkodzie temu, aby po stronie serwera obsługa żądania typu GET usuwała zasób, do którego się odwołuje.

Metody idempotentne to takie, w przypadku których wielokrotne wywołanie powinno przynieść taki sam efekt jak wywołanie jednokrotne. Wśród metod idempotentnych znajdują się metody bezpieczne, PUT (modyfikacja zasobu) i DELETE (usunięcie zasobu). Podobnie ja w przypadku metod bezpiecznych implementacja takiego zachowania leży po stronie aplikacji, a nie samego protokołu HTTP. Nie można z góry zakładać tej cechy danego zapytania jedynie na podstawie metody HTTP.

Kody HTTP

Kody odpowiedzi protokołu http dzielą się na 5 grup:

  • 1XX Informacja (np. 100 Continue)
  • 2XX Sukces (np. 200 OK, 201 Created, 202 Accepted)
  • 3XX Przekierowanie (np. 301 Moved Permanently)
  • 4XX Błąd klienta (np. 400 Bad Request, 404 Not Found, 418 I'm a teapot ☕)
  • 5XX Błąd serwera (np. 500 Internal Server Error, 508 Loop Detected)

Zasady REST

REST, czyli REpresentational State Transfer, to styl architektury systemów rozproszonych. Rest definiuje zbiór zasad mówiących o tym, jak powinno projektować się API. O API spełniających te zasady można powiedzieć, że są RESTful. Zasady stylu REST to:

  • Podział klient-serwer. Ta zasada odnosi się do wprowadzenia jasnego podziału między zadaniami aplikacji-klienta i aplikacji-serwera. Na przykład aplikacja-serwer dostarcza dane w formacie json, a aplikacja-klient wyświetla na ich podstawie tabelę i formatuje dane w sposób czytelniejszy dla użytkownika. Pozwala to na tworzenie łatwiejszych w zrozumieniu i lepiej skalujących się aplikacji.
  • Bezstanowość. Cecha ta mówi o tym, że wszystkie informacje potrzebne do wykonania żądania muszą być zawarte w danym żądaniu. Oznacza to czasami konieczność przechowywania pewnych informacji (np. tokena uzyskanego po zalogowaniu się) po stronie klienta i dodawanie ich do kolejnych żądań.
  • Możliwość buforowania (cache). Mechanizm cache ma na celu zmniejszenie liczby zapytań wysyłanych do aplikacji-serwera. Jeśli wcześniej uzyskana odpowiedź jest oznaczona jako wspierająca mechanizm cache, może zostać ona zapisana po stronie aplikacji klienta. Podczas kolejnej próby wykonania podobnego żądania aplikacja-klient sprawdza, czy nie posiada już odpowiedzi z takiego zapytania. W przypadku, gdy klient posiada taką odpowiedź (i dodatkowo nie minął termin jej aktualności) można skorzystać z niej, zamiast wykonywać kolejne żądanie. Jest to bardzo przydatny mechanizm, ale jego zastosowanie ogranicza się tylko do przypadków, gdzie akceptowalne jest korzystanie z potencjalnie nieaktualnych danych.
  • Uniwersalność interfejsu. Ta zasada skupia się na wprowadzaniu standardów zapewniających jednolitość sposobów komunikacji. Aplikacje spełniające tę zasadę stają się bardziej re-używalnymi blokami, które łatwiej podmienić. Uzyskanie tego możliwe jest przez stosowanie czterech mniejszych zasad:

    • Identyfikacja zasobów — każdy zasób powinien mieć stały identyfikator pozwalający na precyzyjne odwoływanie się do niego.
    • Manipulacja zasobami poprzez reprezentację — w komunikacji między klientem a serwerem nie uczestniczą bezpośrednio zasoby, których dotyczy komunikacja, a jedynie ich reprezentacja (np. json). Klient, wysyłając żądanie, może wskazać, jakiej reprezentacji oczekuje w odpowiedzi. Podobnie wygląda sytuacja podczas modyfikacji zasobu, tu klient wysyła dane reprezentujące zmieniony stan (np. xml), ale zmiany samego zasobu przeprowadzane są już po stronie aplikacji publikującej API.
    • Samoopisujące się wiadomości — przykładem stosowania tej zasady może być dodawanie nagłówka określającego format danych zawartych w ciele (body) żądania. Dzięki temu dane żądanie zawiera komplet informacji potrzebnych do zrozumienia.
    • Hipermedia jako silnik stanu aplikacji (HATEOAS) — odpowiedzi oprócz informacji dotyczących samego zasobu powinny zawierać w sobie odniesienia do dostępnych akcji i zasobów powiązanych. Umożliwia to stopniowe odkrywanie struktury API przez konsumenta.
  • Warstwowość. Ten punkt odnosi się do zapewnienia możliwości krokowej obsługi żądania w sposób niezauważalny dla klienta. Pozwala to na delegowanie części odpowiedzialności do osobnych aplikacji. W przetworzeniu żądania oprócz aplikacji udostępniającej konkretne dane API mogą brać udział inne aplikacje. Na przykład: podczas wykonywania zapytania do API A sprawdzane są uprawniania klienta przy pomocy API B oraz pobierane są dodatkowe zasoby z API C. Jednak z perspektywy klienta istotne powinno być tylko wysłanie zapytania do API A. Cała reszta powinna być ukrytym szczegółem implementacji.
  • Kod na żądanie. Jest to zasada opcjonalna. Mówi ona o możliwości przesyłania kodu w odpowiedzi na żądanie. Taki kod może być później wykonany po stronie klienta API.

Zasady opisane w ramach stylu REST, jak i cześć wytycznych dotyczących protokołu HTTP są jedynie wskazówkami pozwalającymi budować przejrzyste i uniwersalne interfejsy komunikacji między aplikacjami. Należy pamiętać o tym zarówno podczas tworzenia aplikacji konsumującej, jak i publikującej API. Nie można ich brać za pewnik ani nie trzeba przestrzegać za wszelką cenę. Stosowanie się do ogólna przyjętych zasad może potencjalnie przynieść znaczące korzyści, jednak czasami nagięcie zasad w celu lepszego obsłużenia konkretnych przypadków może być w pełni uzasadnione. Oprócz przedstawiony w tym wpisie API REST istnieją inne popularne sposoby komunikacji między aplikacjami takie jak na przykład SOAP, czy GraphQL.

Źródła: