Najważniejsze zagadnienia, które musisz znać
5 godz. 53 min · JavaScript · Full-stack i Programowanie
Adam GospodarczykPrzesyłanie oraz transformacja danych to jeden z najważniejszych elementów działania każdej aplikacji. Dobre zrozumienie tego w jaki sposób odbywa się ten proces, daje równocześnie lepsze zrozumienie całej struktury oraz podejmowania decyzji projektowych. W tym kursie znajdziesz lekcje, które pozwolą Ci uporządkować wiedzę na temat protokołu HTTP oraz formatów wymiany danych.
REST oraz GraphQL to nadal nieodłączone zagadnienia tematu wymiany informacji w kontekście aplikacji webowych. Pomimo tego, że ich koncepcje zwykle są bardzo dobrze opisane w różnych źródłach, tak ich wykorzystanie "na produkcji" potrafi sprawić problemy. W szczególności gdy weźmiemy pod uwagę, wyjątki oraz fakt, że nie każda aplikacja będzie wymagać implementacji REST czy GraphQL w 100%. W tym kursie znajdziesz wiele praktycznych wskazówek związanych z pracą z REST API oraz wprowadzenie do pracy z GraphQL.
Niektóre błędy w aplikacji są bardzo pożądane, w szczególności gdy jasno informują użytkownika o tym, co się wydarzyło oraz o tym, co może z tym zrobić. Pomimo tego, że w wielu przypadkach opracowanie komunikatów leży w rękach osoby odpowiedzialnej za copywriting (i/lub ux writing), tak sama implementacja tych komunikatów odbywa się po stronie kodu. Nie rzadko okazuje się, że poprawna i skuteczna walidacja danych oraz obsługa błędów nie jest oczywista w "produkcyjnych" sytuacjach. W tym kursie znajdziesz najczęściej spotykane problemy oraz sposoby ich rozwiązania.
Bazy danych są praktycznie nieodłączną częścią każdej aplikacji. W roli full-stacka prędzej czy później przyjdzie Ci z nimi pracować a nie rzadko nawet projektować oraz rozbudowywać ich struktury. W tym kursie znajdziesz informacje o bazach danych, które pozwolą Ci je zrozumieć oraz od razu poznać użyteczne techniki, które pomogą Ci w pracy z nimi, zarówno na produkcji jak i w środowisku lokalnym czy testowym.
Nie wszystkie informacje w aplikacji są publiczne. Niektóre wprost nie mogą takie być. Z tego powodu niezbędne są sposoby na to aby poznać a potem weryfikować tożsamość użytkownika, by na jej podstawie przydzielać mu dostęp wyłącznie do zasobów, do których odczytywania posiada uprawnienia. Istnieje wiele technik, które umożliwiają zarządzanie dostępem do danych i w tym kursie poznasz najważniejsze z nich. Dowiesz się nie tylko w jaki sposób zabezpieczać dane ale poznasz też najpopularniejsze sposoby na to aby te zabezpieczenia łamać i obchodzić. Mając świadomość takiej możliwości, będziesz w stanie lepiej podejmować decyzje o tym jak projektować dostęp do informacji.
Istnieją problemy charakterystyczne dla niemal każdej aplikacji. W związku z ich powszechnością, istnieje też szereg rozwiązań lub sposobów na to, aby możliwie zredukować ich następstwa. Na przestrzeni lekcji tego kursu zobaczysz wiele przykładów, które pomogą Ci w codziennej pracy a niekiedy nawet, pozwolą uniknąć błędów, których konsekwencje nie zawsze występują natychmiast.
Kurs powstał z myślą o osobach, które chcą rozwijać się w roli full-stack web developera / developerki, przeprowadzając przez najważniejsze zagadnienia z obszaru wymiany, transformacji oraz przechowywania informacji w aplikacji oraz pomiędzy aplikacjami. Jeżeli potrzebujesz zobaczyć szeroką perspektywę tego, w jaki sposób dane przepływają pomiędzy różnymi częściami aplikacji, lub ugruntować swoją wiedzę na ten temat, to ten kurs jest miejscem, którego szukasz.
No to teraz przechodzimy do Sets REST API i tego w jaki sposób projektować end
pointy i tym samym też projektować całą komunikację, która będzie odbywać się
pomiędzy klientem bądź klientami oraz serwerem bądź serwerami.
Endpoint to jak już wiesz, nic innego jak adresy URL, które mogą wyglądać np.
w taki sposób.
REST API definiuje to, że wykorzystujemy metody HTTP do tego, aby to cudo używać
akcji, które mogą być wykonywane dokładnie na tym samym.
Endpoint serwer będzie w stanie rozróżnić na podstawie metody HTTP to z jaką akcją
mamy doczynienia i tym samym też co ma zrobić oraz jaką odpowiedź zwrócić.
W tym przypadku GET symbolizuje nam pobieranie danych z Endpoint API Users,
czyli po prostu pobieramy informacje na temat użytkowników.
Tutaj w tym miejscu już to pominę.
Natomiast pamiętaj o tym, że należy zadbać o odpowiednie nagłówki oraz ustawienie
statusów odpowiedzi oraz też samej struktury odpowiedzi.
Te wszystkie tematy omawialiśmy już w
poprzednich modułach, więc nie ma potrzeby ich powtarzać.
Natomiast to wszystko właśnie w tym miejscu będzie się ze sobą łączyć.
I teraz jeszcze tylko dla przykładu pokażę Ci w jaki sposób np.
pobierać informacje o użytkownikach z
dodatkowymi ograniczeniami kontrolowanymi ze strony klienta.
W tym przypadku klient pyta o
użytkowników, ale chce pobrać informacje tylko o pierwszych dziesięciu.
Teoretycznie sytuacja wygląda tutaj bardzo prosto, ponieważ serwer musi tylko
odczytać ten parametr, a następnie przygotować zapytanie np.
SQL w taki sposób, aby odpowiedź zawierała tylko 10 rekordów.
Bardzo istotne jest również to, aby w
takiej sytuacji serwer zadbał również o to, aby umożliwił pobranie np.
kolejnych 10 rekordów.
Oznacza to, że wraz z odpowiedzią ma wrócić jakaś informacja o tym, w jaki
sposób klient może zapytać o kolejny zestaw danych.
Oczywiście to w jaki sposób zaprojektuje się taki system zależy już od Twojej
aplikacji i przez przykłady implementacji będziemy przechodzić.
Natomiast musisz wiedzieć, że sytuacja się tutaj może mocno skomplikować.
Przykładem może być chociażby sytuacja, w której chcemy pobrać tylko dziesięciu
użytkowników, w przypadku których ich ocena jest większa bądź równa 10.
W takiej sytuacji akurat tutaj stosujemy nawiasy kwadratowe, w tutaj przekazujemy
oznaczenie, jaki konkretnie zakres nas interesuje.
Natomiast naturalnie moglibyśmy zastosować
tutaj inną strukturę przekazania tej informacji.
Po prostu to co widzisz tutaj to nic innego jak dobre praktyki.
One akurat nie są wprost definiowane przez
rest API, ale bardzo często spotykane na przestrzeni różnego rodzaju aplikacji.
I przykładowo mamy tutaj artykuł opisujący
temat filtrowania oraz różnego rodzaju podejścia, które mogą być zastosowane
zarówno po stronie frontendu, jak i oczywiście po stronie backendu.
Musimy je obsłużyć.
No i tutaj w tym przypadku, w momencie gdy
stosujemy nawiasy kwadratowe, mamy specjalne narzędzie do parsowania takich
informacji i zamiany ich na strukturę Jameson.
W ten sposób otrzymujemy obiekt, które możemy wykorzystać np.
z pomocą tak zwanego O1, a które
przygotuje dla nas odpowiednie zapytanie do bazy danych.
Podobnie też alternatywą dla tych nawiasów
jest znak dwukropka, który to również ma swoje jakieś zalety oraz wadę.
Na koniec dnia trzeba pamiętać o tym, że istnieje właśnie kilka różnych podejść,
które możesz zastosować i jak zwykle zalecam tylko to, aby zdecydować się na
któryś z nich, który najbardziej odpowiada potrzebom Twojej aplikacji, a następnie
zachować absolutną spójność w tym, aby się jego trzymać.
Oczywiście czasem mogą zdarzyć się sytuacje, w której podejmiemy złą decyzję
na samym początku i potem będziemy musieli ją zmienić.
Natomiast w niektórych sytuacjach nie
będzie to możliwe i skończymy z dwiema różnymi wersjami naszego API.
Oczywiście warto takich sytuacji uniknąć
możliwie jak najwcześniej, ale jednocześnie ponownie mówimy tutaj o
doświadczeniu i ewentualnej możliwości popełnienia zwykłych błędów.
Zatem na temat zapytania typu get musisz
wiedzieć, że służy ono do pobierania danych i konkretnie.
W przypadku tej operacji możemy
wykorzystać parametr query string do tego, aby manipulować strukturą odpowiedzi.
To, co najbardziej Cię zainteresuje to
przede wszystkim limitowanie tagi, nazwa oraz filtrowanie.
Są to przykłady najczęstszych parametrów, z którymi będziesz mieć do czynienia,
które musisz zaadresować po stronie serwera.
Kolejnym przykładem wykorzystania zapytania GET jest zapytanie o konkretny
zasób, bo właśnie w momencie gdy mamy adres API users to juz jest to nic innego
jak nasze zasoby, a jeden użytkownik to nasz zasób.
Zwykle pojedynczy zasób identyfikowany jest w formie unikatowego identyfikatora.
Najczęściej jest to liczba bądź też tzw.
unikatowy identyfikator, który składa się
z serii znaków, które są unikatowe na przestrzeni całej bazy danych.
Tak jak już przynajmniej kilka razy to powtarzałem, takie identyfikatory
najczęściej narzucane są przez bazę danych w momencie.
Nia nowego rekordu.
W ten sposób upewniamy się, że te identyfikatory są przede wszystkim
unikatowe, ale też, że są w sposób bezpośredni powiązane z konkretnym wpisem.
Dodatkowo nie wiem, czy zdajesz sobie z tego sprawę, ale nawet takie rzeczy jak
liczba mnoga oraz pojedyncza w przypadku zasobów odgrywają tutaj ważną rolę.
Mianowicie teoretycznie mógłbym napisać
tutaj API użytkownicy, natomiast moim zdaniem znacznie lepiej
jest stosować tutaj nazwy angielskie i właśnie w liczbie mnogiej.
Wynika to z faktu, że jest to dość logiczne, że w momencie gdy wysyłamy
zapytanie na users pytamy o użytkowników, a jeżeli o users
identyfikator pytamy o konkretnego użytkownika o konkretnym identyfikatorze.
I swoją drogą zwróć uwagę, że jedynka,
czyli też identyfikator nie stanowi tutaj właściwości przekazywanej z pomocą query
string, tylko jest to zwykły parametr adresu URL.
Taki parametr po stronie backendu jest
odczytywany w nieco innej formie i też w next jest.
Dowiesz się w jaki sposób możemy to zrobić.
Pamiętaj tylko proszę o tym, że parametr
adresu URL to nie jest to samo co parametr składy string.
Idąc dalej mamy tutaj jeszcze jeden przykład tzw.
zagnieżdżonych zasobów, z którymi również możesz się spotkać.
Ja osobiście unikam ich zastosowania, gdy
to tylko możliwe ze względu na to, że moim zdaniem komplikują zarówno API po stronie
użytkownika, ale też po stronie samej implementacji.
Mianowicie sama logika wydaje się tutaj dość sensowna.
Mamy zapytanie o użytkowników, a konkretnie użytkownika o identyfikatorze 1
oraz jego artykuły, czyli powiązane z nim zasoby.
W tym konkretnym przypadku pytamy jeszcze o zasób o identyfikatorze 3.
Coś takiego faktycznie teoretycznie jest dość logiczne.
Pytamy o konkretnego użytkownika i jego konkretny artykuł.
Na poziomie teorii wszystko się zgadza.
Na poziomie jednak praktyki zaczyna komplikować.
Otóż chodzi o to, że.
Wyobraź sobie, że wysyłasz takie zapytanie po stronie klienta.
W momencie, gdy to robisz, musisz znać nie
tylko ID użytkownika, ale również artykuł, którego szukasz.
Oczywiście mógłbyś w pierwszej kolejności zapytać o użytkownika, a następnie
wyświetlić jego wszystkie artykuły, a następnie wyszukać konkretny artykuł.
Natomiast już na tym etapie widać, jak bardzo jest to skomplikowane.
Jednocześnie, jeżeli będziesz mieć po
prostu dodatkowe endpoint o nazwie API Articles, będziesz w stanie przekazać np.
parametr Query string o nazwie User id, gdzie podasz identyfikator użytkownika.
Sytuacja jest tutaj zdecydowanie prostsza zarówno po stronie klienta, jak i serwera.
Jednocześnie miej na uwadze fakt, że w przypadku serwera mówimy tutaj o
parametrach, które nie są odpowiednio identyfikowane, czyli np.
mamy Article, id oraz User id.
Pod tymi zmiennymi zostaną przekazane
odpowiednie identyfikatory, które możesz wykorzystać po stronie akcji kontrolera.
Zatem moim zdaniem zdecydowanie lepiej jest skorzystać z opcji posiadania
oddzielnego zasobu, ponieważ w takiej sytuacji możesz pobrać np.
wszystkie artykuły i w żaden sposób w tej
sytuacji nie uwzględniać informacji na temat użytkowników.
Naturalnie w tym wszystkim musisz pamiętać o tym, aby w momencie, gdy np.
użytkownik o identyfikatorze 1 wykonuje
zapytanie o artykuł o identyfikatorze 3, to musisz za każdym razem upewnić się, że
jest ono uprawnione do tego, aby go odczytać.
Idąc dalej za metodą GET mamy metodę POST, która jak widzisz korzysta z dokładnie
tego samego endpoint, z tą różnicą, że metoda HTTP ustawiona na post pozwala nam
przede wszystkim przekazać ciało zapytania i też mowa tutaj o danych użytkownika,
które w tym przypadku zostaną dodane do naszej bazy.
Zapytanie POST najczęściej wykorzystywane jest w celu tworzenia nowych zasobów,
czyli tego, aby w tym przypadku utworzyć nowego użytkownika.
Ponownie odwołuję się do lekcji na temat
komunikacji i przygotowywania odpowiednich struktur do odpowiedzi, aby chociażby w
momencie tworzenia nowego użytkownika wraz z informacjami na jego temat zwrócić
również jego identyfikator, który został utworzony przez bazę danych po stronie
serwera, ale też nie przesyłać danych wrażliwych, takich jak np.
hasło, które podał użytkownik.
Natomiast co do zasady metody POST
wykorzystywane są na całej kolekcji, a nie na pojedynczych elementach.
Następnie mamy metodę PUT, która wykorzystywana jest po to, aby
zaktualizować rekord o konkretnym identyfikatorze.
Ważne jest jednak to, że mamy jeszcze
metodę, która zasadniczo robi dokładnie to samo, z tą różnicą, że w przypadku metody
patch możemy zaktualizować tylko częściowe pola użytkownika, czyli np.
jego adres email bądź ocenę, a w przypadku metody PUT przesyłamy cały
obiekt użytkownika, który miałby zostać podmieniony w bazie danych.
Oczywiście poza samym identyfikatorem, który powinien zostać stały.
W tym wszystkim jednak istotne jest to, że bardzo często spotkasz się z API, które
nie wykorzystują w ogóle metody PUT oraz page, tylko w zamian wysyłają zapytanie
typu POST na adres zawierający identyfikator.
Czyli np. coś takiego.
Wynika to z faktu, że znowu jest to decyzja projektowa.
Chodzi o to, że w niektórych sytuacjach być może z jakiegoś powodu nie ma potrzeby
implementowania dodatkowych metod, które z pewnością zwiększają złożoność naszej
aplikacji, a jednocześnie w niektórych przypadkach nie będą wnosić zbyt wiele
poza informacją, co tutaj dokładnie się odbywa.
No bo teoretycznie jeżeli nie chcesz to put oraz patch, no to możesz
wykorzystać metodę POST i dość łatwo się domyślić, że chodzi tutaj o
zaktualizowanie użytkownika o konkretnym identyfikatorze.
Natomiast na koniec dnia musisz wiedzieć,
że te metody istnieją i że ich rola jest taka, a nie inna.
To czy jest będziesz z nich korzystać
projektując swoje API zależy w dużym stopniu od Twojej decyzji.
No i ostatnią metodą, która w
przeciwieństwie do metody PUT jest dość często wykorzystywana jest metoda direct.
Niemal zawsze wykorzystywana jest ona na
pojedynczych zasobach i umożliwia ich całkowite usunięcie.
Ponownie zaznaczam tutaj wątek dotyczący
sposobu obsługi samego procesu usuwania rekordów z bazy danych.
Większość tutoriali i książek wskazuje, że po prostu wystarczy usunąć informacje na
temat konkretnego zasobu i wszystko jest w porządku.
Natomiast moje doświadczenie wskazuje, że jednak wygląda to trochę inaczej i w
większości przypadków raczej będzie chodziło nam o pewien sposób
archiwizowania danych ze względu na to, aby można było zachować informacje np.
na potrzeby raportów i wskaźników
aplikacji, które nie mogą się zmieniać w momencie, gdy np.
użytkownik usunie swoje konto.
Z drugiej jednak strony, w momencie, gdy
użytkownik to konto będzie usuwał, musimy zadbać o jego bezpieczeństwo danych i to,
aby jakikolwiek ślad, który pozostał po jego obecności, nie mógł być w żaden
sposób powiązany z tym konkretnym użytkownikiem.
Jeżeli chcesz dowiedzieć się więcej w tym obszarze, polecam kontakt z działem
prawnym oraz poruszenie tematu dotyczącego anonimizacji użytkowników.
Z punktu widzenia prawnego właśnie tak to może być zaadresowane.
Ale jednocześnie to Twoim zadaniem będzie przeniesienie tych zasad prawnych na
reguły, które wykorzystasz w ramach swojej aplikacji.
Z mojego punktu widzenia w większości
przypadków, bo nie zawsze istotne jest tylko to, aby zachować jakikolwiek ślad
pozwalający wygenerować raport dotyczący np.
rozwoju naszej aplikacji.
I teraz w temacie najważniejszych zasad dotyczących budowania end pointów za
pomocą rest API to w zasadzie byłoby na tyle.
Jak widzisz, te zasady są stosunkowo bardzo proste, ale jednocześnie istnieje
bardzo wiele przykładów, gdzie nie będziemy mogli wykorzystać tych zasad.
Czasem będziemy musieli iść na pewne ustępstwa, a czasem będziemy musieli wręcz
złamać tę zasadę, aby zrealizować jakieś założenie naszej aplikacji.
Jednocześnie im bardziej będziesz trzymać się tych zasad REST API, tym bardziej
zwiększysz użyteczność swojego API, jego intuicyjność oraz też wygodę zarówno
użytkowników, jak i swoją i innych osób, które będą z tego API korzystać.
Myślę, że na ten moment to byłoby na tyle.
Dziękuję Ci więc za uwagę i zapraszam do kolejnej lekcji.