Poznajmy Postman’a!

Podczas rozwijania API chcielibyśmy w łatwy sposób przetestować, czy działa ono jak należy i zwraca wartości w takiej formie, w jakiej powinno. Chciałem dzisiaj opisać pokrótce narzędzie, które nadaje się to tego celu idealnie. Znam je od dawna, ale dopiero niedawno poznałem większość z jego sporych możliwości. Mowa tutaj o Postman’ie. Jest to darmowa aplikacja, która pozwala na wykonywanie zapytań oraz przechowywanie ich historii. Zapraszam na krótkie wprowadzenie.

Logo narzędzia Postman

Instalacja

Tutaj sprawa jest bardzo prosta, jeżeli mamy przeglądarkę Chrome, wystarczy że dodamy rozszerzenie, które można pobrać tutaj. Drugą opcją jest zainstalowanie natywnej aplikacji na nasz system. Ją z kolei możemy pobrać w tym miejscu. Natywna aplikacja omija kilka ograniczeń wersji z dostępnej w przeglądarce. Następnie zakładamy konto i logujemy się do aplikacji. Możemy przejść dalej!

Podstawowe funkcje

Aplikacja moim zdaniem ma bardzo przyjemny dla oka interfejs, ale łatwo przeoczyć tutaj kilka ciekawych funkcji. Na początek zajmijmy się jednak kilkoma podstawowymi rzeczami. W menu bocznym aplikacji możemy dodawać kolekcje, które będą przechowywały nasze zapytania. Możemy tutaj także zobaczyć historię ostatnio wykonanych requestów.

Kolekcje w postmanie

Kolekcje oraz historia

Kolekcje przechowują nasze zapytania. Dodajmy więc nowy request. Wybieramy typ zapytania z listy oraz adres który będziemy odpytywać.

Nowe zapytanie

Możemy wybrać typ zabezpieczeń który jest zaimplementowany w API, dodać nagłówki oraz parametry naszego zapytania. Następnie klikamy na przycisk Send i gotowe. W odpowiedzi dostaniemy status naszego zapytania, czas wykonania, rozmiar odpowiedzi, body, ciasteczka, nagłówki. Nasze zapytanie możemy zapisać w kolekcji i szybko wykonać je ponownie później.

Animacja pokazująca wykonanie zaptania

Wykonanie zapytania

Environments

Bardzo przydatną opcją Postmana jest możliwość tworzenia profili środowiska. Jest to niesamowicie pomocne gdy chcemy w szybki sposób testować naszą aplikację lokalnie, a zaraz potem już na produkcji lub środowisku testowym. Dzięki temu nie musimy dodawać wielokrotnie tego samego zapytania lub ciągle edytować tych już istniejących.

Zarządzanie środowiskami

Definiujemy tutaj adres naszego API, istniejący token, nazwę użytkownika, hasło lub cokolwiek innego. Dodajemy takie opcje zarówno dla środowiska dev jak i produkcyjnego.

Edycja środowiska

Edycja środowiska

Następnie, tam gdzie nasze dane będą zależne od środowiska, zamiast podawać te wartości, wstawiamy zmienne środowiskowe. Zostaną one automatycznie zastąpione wartościami zdefiniowanymi w aktywnym środowisku. W tym celu używamy podwójnych nawiasów klamrowych, na przykład {{url}}.

Użycie zmiennych środowiskowych

Użycie zmiennych

Tesy oraz skrypty

Kolejną przydatną rzeczą są testy oraz skrypty wykonywane przed zapytaniem. Przed wykonaniem zapytania możemy np. ustawić obecną godzinę do zmiennej. Podobnie do skryptów działają testy.
Służą one do kilku celów. Pierwszym i oczywistym jest możliwość sprawdzenia czy wynik który otrzymaliśmy jest poprawy, posiada wszystkie pola, odpowiedni status etc. Podobnie jak w przypadku skryptów, możemy ustawić tutaj zmienną, ale tym razem mamy dostęp do tego, co zwróciło nasze zapytanie. Możemy więc wysłać zapytanie np. o token, a następnie przypisać go do zmiennej.

Taka automatyzacja może nam bardzo przyśpieszyć pracę. Nie będziemy musieli sprawdzać wszystkiego samemu, co może być problemem przy większej ilości zapytań.

Test zapytania

Testy zapytania

Wykonywanie wielu zapytań

Ostatnią rzeczą którą chciałem pokazać jest wykonywanie wielu zapytań jednocześnie, co umożliwia nam Collection Runner. Przy jego pomocy możemy wykorzystać to, o czym pisałem w poprzednim akapicie. Przykładowo, jako pierwsze zapytanie w kolekcji dodajemy takie, które odpyta nasze API o token uwierzytelniający. Zapytanie te zapisze nasz token do zmiennej,
z której później będą korzystały inne zapytania. W ten sposób możemy automatyzować wykonywanie i testowanie bardzo dużej ilości zapytań.

Podsumowanie

Mam nadzieje że tym, którzy nie znali jeszcze tego narzędzia pokazałem, jak w łatwy sposób z niego korzystać i ułatwić sobie życie. Po więcej informacji dotyczących Postmana odsyłam na jego oficjalną stronę, gdzie można znaleźć więcej przykładów i dokładny opis funkcji o których tutaj nie wspomniałem.

Przygotowanie API – REST, czy nie do końca?

Pracę nad moim projektem zacząłem od zadania sobie pytania: jak powinna wyglądać architektura mojego programu? I chociaż na temat samej architektury dodam oddzielny post, potrzebne będzie krótkie wprowadzenie. Głównym założeniem jest powstanie aplikacji dostępnej z poziomu przeglądarki, dzięki czemu będzie można uruchomić ją na komputerach PC oraz Mac, tabletach, a nawet smartfonach. Wiadomo jednak, że na urządzeniach przenośnych dużo wygodniej korzysta się z aplikacji natywnych. Tak powstał kolejny cel, czyli apka na urządzenia zaopatrzone w system Android. Nie postanowiłem jeszcze jak będzie ona wyglądać, ale skłaniam się ku rozwiązaniu w którym będzie ona miała ten sam kod (w miarę możliwości) co strona www, dzięki zastosowaniu rozwiązań takich jak np. Adobe PhoneGap. Jeżeli tak się sprawy mają, to naturalnym wnioskiem dla mnie jest to, że muszę przygotować jakieś API, które mój klient będzie mógł wykorzystać. Tutaj pojawia się kolejne pytanie, na które chcę dzisiaj odpowiedzieć: czy moje API powinno być RESTful, czy też nie? Może wystarczy podejście RPC.

REST czy RPC? I co to takiego?

W celu podjęcia decyzji, postaram się w skrócie opisać te dwa podejścia i wskazać czym się różnią. Oba z tych rozwiązań w tym kontekście operować będą na protokole HTTP. Zapytanie przy użyciu tego protokołu składa się z między innymi:

  • Metody (Mehtod) np. GET, HEAD, POST, która decyduje o tym jaką operację wykonamy na zasobie
  • Nagłówków (Header), w których dostępne są dodatkowe informacje o żądaniu np. dane pozwalające na uwierzytelnianie
  • Ciała zapytania (Content body), które przechowuje informacje np. o zasobie który chcemy dodać/edytować

Niektóre z metod są idempotentne (Idempotent) (z założenia, tak powinny być zaimplementowane), to znaczy że nie ważne ile razy je wykonamy w danych warunkach, zawsze zwrócą tej sam wynik (np. GET i PUT). Inną cechą niektórych metod jest to że są bezpieczne (Safe), czyli nie modyfikują one danych i nie posiadają skutków ubocznych np. GET i HEAD (tak jak poprzednio, w ten sposób powinny być implementowane).

REST, czyli Representational State Transfer to architektura pozwalająca na pisanie skalowalnych usług internetowych. Nie będę rozpisywał się na temat definicji pojęcia REST. Opisując w skrócie: udostępniamy zasoby na których możemy wykonywać różne operacje za pomocą protokołu HTTP. Rodzaj operacji zależy od tego, jakiej metody użyjemy podczas zapytania. Przykładowo, poniższe trzy zapytania będą miały różne wyniki:

  • GET www.example.com/api/objects/2
  • DELETE www.example.com/api/objects/2
  • PUT www.example.com/api/objects/2

W przypadku, gdy mówimy o REST, mamy na myśli podejście zorientowane na zasoby. Definiując adres zasobu używamy rzeczowników, a to jaką akcję wykonujemy nie jest wskazywane przez dodanie czasownika, lecz przez wybór metody HTTP.

RPC (Remote procedure call) ma wiele definicji, ale w tym znaczeniu chodzi o podejście, w którym zamiast operować na zasobach, mamy do czynienia z operacjami. Operacje te w swojej nazwie sugerują co będzie efektem ich wykonania. W przypadku implementacji tego podejścia za pomocą protokołu HTTP wykorzystuje się głównie dwie metody: GET oraz POST. Nie ma tutaj jasno sformułowanych zasad, ale zazwyczaj GET służy do pobierania danych lub akcji, które nie zmieniają żadnych danych, natomiast POST służy do pozostałych operacji. Przykładowe wywołanie takich zapytań:

  • GET www.example.com/api/GetAllObjects
  • POST www.example.com/api/CreateObject

Jeżeli wiemy już jak takie zapytania wyglądają i czym się charakteryzują, możemy przystąpić do porównania. Wezmę pod uwagę kilka czynników, które moim zdaniem są ważne podczas wyboru metody implementacji naszego API.

Projektowanie

Na początek weźmy pod uwagę to, w jak łatwy sposób można projektować nasze API. Jeżeli weźmiemy pod uwagę systemy, które już istnieją np. mamy napisaną już bibliotekę i chcemy w jakiś sposób wyprowadzić ją na świat, łatwiej będzie nam użyć podejścia RPC. Dzieje się tak z reguły dla tego, że większość kodu jaki piszemy jest zorientowany na operacje i łatwiej go w ten sposób odwzorować. Łatwiej też będzie rozwijać system, który głównie opiera się o różnego rodzaju procesy, gdzie jeden obiekt ciągle zmienia się wg jakiejś logiki. Wadą tego podejścia może być to, że ponieważ nie nakłada nam ona żadnych ograniczeń, projektant musi sam pilnować tego, żeby API było spójne i składało się w logiczną całość. Z drugiej strony, REST ułatwia projektowanie prostszych systemów gdzie głównym zadaniem są operacje typu CRUD. Nawet, jeżeli projektowanie API RESTowego może być trudniejsze, dzięki założeniom jakie ze sobą niesie łatwiej otrzymać spójne i logiczne zaplecze dla naszej aplikacji. Tutaj pytanie pozostaje bez odpowiedzi moim zdaniem, ponieważ wszystko zależy od kontekstu w jakim będziemy pracować.

Dokumentacja i jak łatwo ją przygotować

W obu przypadkach możemy wykorzystać narzędzia typu Swagger do udokumentowania naszego API, więc żadne podejście nie jest tutaj lepsze. Sama nazwa zasobu/operacji także może nam sporo powiedzieć o tym, co będzie efektem wywołania danego zapytania. GET www.example.com/api/GetAllObjects czy GET www.example.com/api/objects w jasny sposób mówi nam, co dostaniemy w odpowiedzi, więc można tutaj powiedzieć w pewnym stopniu o tym jak API dokumentuje się samo. Z doświadczenia wiadomo jednak, że takie rzeczy nie zdarzają się zbyt często i trzeba posiłkować się dodatkowymi źródłami wiedzy o naszym requescie.

Semantyka i używalność

W RPC nie jesteśmy w stanie przewidzieć tego, jak dana operacja będzie się nazywać. Ta sama operacja może przybierać taki wygląd:

  • GET/POST www.example.com/api/RemoveObject/1
  • GET/POST www.example.com/api/DeleteObject/1

Zdajemy się tutaj na to, jaki styl wybiera osoba odpowiedzialna za przygotowanie API. Można założyć, że będzie się ona trzymała swojego standardu i podczas usuwania innego rodzaju obiektu użyje tej samej nazwy zapytania. Jednak może się zdarzyć, że za każdym razem trzeba będzie zagłębiać się w dokumentację. REST jest bardziej przewidywalny, dzięki wykorzystywaniu metod HTTP. Nawet, jeżeli nie wiemy dokładnie co stanie się po wykonaniu danej metody, mamy ogólne pojęcie co może być efektem końcowym. W tym przypadku, mój głos dostaje podejście REST, chociaż nie musi zawsze tak być.

Obsługa Cache

Obsługa Cache to jedna z bardzo ważnych rzeczy, które powinna zapewniać nasza RESTowa architektura. Patrząc na specyfikację metod HTTP w łatwy sposób dodać taką obsługę do naszego API. W podejściu RPC jest to dużo trudniejsze, zwłaszcza, gdy zbyt często będziemy korzystać z metody POST. Nie jest to jednak niemożliwe. W tym punkcie można skłaniać się minimalnie w stronę architektury REST.

Podsumowanie

Niektórzy stwierdzą, że wybór naszego podejścia można sprowadzić tylko do osobistych odczuć na temat tego, czy wolimy taki czy inny styl zapytań. Jednak od naszego podejścia w dużej mierze zależy to, w jaki sposób będziemy później pisać nasze aplikacje. Moim zdaniem, głównym czynnikiem jakim powinniśmy się kierować jest to, jaki jest nasz projekt i nie ma sensu od razu zakładać że zrobimy to tak, czy inaczej. Pomimo kilku punktów, w których REST jest lepszym podejściem, np. to że jest bardzo przejrzysty i przewidywalny, ma on też kilka sporych wad i nieudogodnień, które wynikają z jego ograniczeń. Dlatego ja zwykle stawiam na pragmatyzm w moich rozwiązaniach i czerpię to, co najlepsze z danych rozwiązań. Nawet, jeżeli moje API będzie bardziej skłaniało się ku architekturze REST, to nie będę bał się użyć podejścia bardziej skierowanego na operacje. Moim zdaniem POST www.example.com/api/game/1/endturn będzie lepiej opisywało sytuację, niż zmiana właściwości obiektu i wykonywanie konkretnej operacji później.

A jakie jest Twoje zdanie na ten temat? Wszelkie uwagi mile widziane! Zapraszam do komentowania i kolejny raz polecam się na Twitterze!