Chcę zostać kotem internetu – Wstęp do programowania cz.2

devkot.pl 1 rok temu

Przed Tobą drugi artykuł z serii „Chcę zostać kotem internetu – wstęp do programowania”. Mam nadzieję, iż pierwszy Ci się podobał i dzięki niemu poznałeś podstawy działania internetu. W tym artykule dalej skupię się na teorii, ale poruszymy nieco inne kwestie. Czy przeglądając internet zastanawiałeś się kiedyś do czego służy zapis http? W tym artykule przedstawię Ci podstawowe informacje dotyczące tego protokołu.

Jeśli nie widziałeś pierwszego artykułu to nic straconego, możesz to nadrobić tutaj: Chcę zostać kotem internetu – Wstęp do programowania cz.1

Protokół HTTP

Protokół HTTP (ang. HyperText Transfer Protocol) opisuje reguły przesyłania zasobów oraz zasady komunikacji między urządzeniami w architekturze klient-serwer. Bazuje on na żądaniach, wysyłanych przez klienta (np. przeglądarka internetowa) oraz odpowiedziach zwracanych przez serwer. Protokół HTTP nie określa, czym jest zasób, może nim być strona internetowa, obrazek, plik mp3 i wiele innych. Opisuje on jedynie zasady jak taki transfer powinien przebiegać. W większości przypadków do komunikacji klienta z serwerem wykorzystujemy protokół TCP/IP. Każdy zasób posiada swój unikalny identyfikator, który nosi nazwę URI. To właśnie dzięki temu protokołowi po wpisaniu w przeglądarkę adresu portalu internetowego wyświetla się on na Twoim ekranie.

URI

URI (ang. Uniform Resource Identitier) to standard, który pozwala na łatwą i szybką identyfikację zasobu w sieci. Jest zbudowany z ciągu znaków i może zawierać nazwę pliku wraz ze ścieżką do folderu, w którym się znajduje, na przykład: //devkot/artykul.txt.

URL

Skoro już poruszyliśmy temat URI to warto również wspomnieć o URL (ang. Uniform Resource Locator). Jest to podzbiór adresów URI. Jest to format adresowania zasobów, który posiada konkretną i dobrze opisaną specyfikację. Adresy URL składają się z wielu elementów.

Schemat adresu URL:

scheme:[//[user[:password]@]host[:port]][/path][?query][#anchor]

Przykładowy adres:

http://devkot:maciej@www.devkot.pl:80/zostan?kot=it&devkot=true#dzis

W powyższym przykładzie widać, iż adres taki składa się z poniższych elementów:

  • scheme (protokół) – protokół komunikacji między klientem a serwerem (np. https),
  • user – login użytkownika, służy do udzielenia dostępu do zasobu. Wykorzystuje autoryzacje typu Basic (informację o tym znajdziesz w dalszej części artykułu),
  • password – hasło użytkownika, wykorzystywane w autoryzacji typu Basic,
  • host – identyfikuje maszynę w sieci, do której powinno zostać wysłane zapytanie o zasoby,
  • port – określa numer portu, który powinien obsłużyć zapytanie po stronie serwera,
  • path (ścieżka) – identyfikuje lokalizację pliku/akcji na serwerze,
  • ?query (zapytanie) – ciąg znaków w postaci pary nazwy parametru i jego wartości. Pierwszy element query jest poprzedzony znakiem zapytania (?). Natomiast kolejne rozdzielane są znakiem &. Parametru tego używa się do przekazania dodatkowych informacji dla serwera dzięki adresu URL,
  • #achor (kotwica) – wskazuje na określony element w treści, który powinien być wyświetlony. Stosowany jest przy pracy ze stronami internetowymi, pozwala na wskazanie przeglądarce, który element strony powinna wyświetlić. Przeglądarka po otrzymaniu adresu URL z kotwicą np #kontakt wyświetli stronę oraz przeniesie ekran do elementu zawierającego id=”kontakt”.

Żądania HTTP

Komunikacja za pośrednictwem protokołu HTTP bazuje na wysyłaniu żądań do serwera oraz otrzymywaniu od niego odpowiedzi. Pewnie zastanawiasz się czym jest to całe żądanie? Mianowicie żądanie to innymi słowy wiadomość, która powinna być dostarczona do konkretnego serwera. Może ona zawierać dodatkowe informacje, które mogą stanowić podpowiedź oraz dostarczać informacji jak dane zapytanie powinno zostać obsłużone. Na ten moment może wydawać Ci się to niezrozumiałe, ale spokojnie zaraz wszystko się wyjaśni! Warto zaznaczyć, iż jest to tekstowy format przesyłania informacji między klientem, a serwerem. Poniżej postaram się wytłumaczyć strukturę oraz zasady obowiązujące dla HTTP/1.1.

Z czego składa się żądanie HTTP?

Podstawowe żądanie HTTP składa się z definicji metody zapytania (opisałem je w dalszej części artykułu), ścieżki, wersji protokołu HTTP oraz wskazania hosta (serwera docelowego). Poniżej przedstawiłem przykładowe zapytanie HTTP.

> GET / HTTP/1.1 // {Czasownik HTTP} {Path} {Wersja Http} > Host: devkot.pl // Nazwa hosta > // Pusta linijka

Powyższy przykład przedstawia bardzo proste zapytanie wysyłane do serwera. Jego treść składa się z 3 linijek:

  1. Zawiera czasownik HTTP – GET (więcej na temat czasowników/metod HTTP przeczytasz w dalszej części artykułu). Zaraz po nim znajduje się ścieżka do zasobu (część URL od path) oraz wykorzystywana wersja HTTP.
  2. W drugiej linijce znajduje się nagłówek HTTP określający do jakiego hosta powinien zostać przesłany. Pozwala on na określenie docelowej maszyny korzystając z systemu DNS.
  3. Każde zapytanie HTTP zawiera pustą linijkę oddzielającą nagłówki od ciała zapytania. Ciało zapytania to nic innego jak dane które są przesyłane do serwera.

W odpowiedzi na powyższe zapytanie maszyna widniejąca w sieci pod adresem devkot.pl zwróci kod strony, który następnie zostanie wyświetlony przez przeglądarkę. W tym momencie pominę to jak zbudowana jest odpowiedź, ponieważ skupię się na tym bardziej szczegółowo podczas opisu zapytań.

Nagłówki HTTP

Do przesyłania informacji między urządzeniami z wykorzystaniem protokołu HTTP wykorzystywane są nagłówki. Jest para typu klucz:wartość. Nagłówki znajdują się zarówno w zapytaniach jak i odpowiedziach, pomiędzy pierwszą linijką, a ciałem żądania/odpowiedzi. Są to swojego rodzaju metadane. Są odpowiedzialne za opisanie informacji wysyłanych pomiędzy klientem, a serwerem. Najczęściej wykorzystane nagłówki to:

NagłówekOpisPrzykład
Con­tent-TypeOkreśla typ/format przesyłanych danychCon­tent-Type: application/json
Con­tent-LengthOpisuje ilość przesyłanych danychCon­tent-Length: 200
Cook­iePrzesyła zawartość ciasteczek dla danego portalu internetowego. zwykle przesyła wiele wartoś­ci w postaci pary klucz=wartość, które odd­zielane są od siebie średnikami.
Wykorzystywany jedynie w zapytaniach.
Cook­ie: UserId=1;Expired=False;
Set-Cook­ieUstawia wartoś­ci Cook­ie (ciasteczek). Podob­nie jak nagłówek Cook­ie zaw­ier­a pary typu klucz=wartość oddzielone od siebie średnikami.
Wykorzystywany jedynie w odpowiedziach serwera.
Set-Cook­ie: UserID=mkotlarz; SeenTutorial=1
Loca­tionInformuje przeglądarkę, iż zasób został przeniesiony (adres zasobu się zmienił). W ten sposób (w połącze­niu ze sta­tusem np. 302) w aplikacji można przekierowywać przeglądarkę na inną stronę internetową.
Wykorzystywany jedynie w odpowiedziach serwera.
Loca­tion: http://www.devkot.pl/nowawersja
HostZawiera informacje dotyczącego tego gdzie znajduje się serwer który powinien obsłużyć żądanie. Może zawierać zarówno nazwę domeny jak i adres IP.
Jest to obowiązkowy nagłówek w zapytaniach.
Host: www.devkot.pl
AcceptOkreśla jakiego typu odpowiedzi spodziewa się klient. Dzię­ki temu ser­w­er może zade­cy­dować o wysła­niu odpowiedzi np. w XML a nie JSON, co ma zas­tosowanie w wielu API.
Nagłówek jest wykorzystywany tylko i wyłącznie w zapytaniach
Accept: application/json
Cache-controlOkreśla instrukcje dotyczące zapisywania odpowiedzi w pamięci podręcznej przeglądarki. Opisuje czy jak i gdzie odpowiedź może zostać zapisana oraz jak długo przeglądarka powinna ją przechowywać. Więcej na temat tego nagłówka możesz przeczytać tutaj: Cache control
Wykorzystywany w odpowiedziach serwera.
Cache-control: public, max-age=1234

Czasowniki (metody) HTTP

Specyfikacja HTTP, wyróżnia wiele rodzajów czasowników (metod) HTTP. Każdy z nich jest bezpośrednio powiązany z zapytaniami wysyłanymi przez klienta oraz ma swoje własne zastosowania. Służą one do rozgraniczania różnych zadań, które mamy zamiar zlecić serwerowi. Początkowo protokół HTTP został projektowany do obsługi plików oraz pozwalał na pobranie(GET)/wysłanie(POST)/aktualizację(PUT) oraz usunięcie(DELETE) pliku. W dobie przeglądarek internetowych i nowoczesnych portali metody te niekoniecznie są wykorzystane do obsługi plików, ale ich semantyka została bardzo zbliżona. Poszczególne metody różnią się od siebie nie tylko przeznaczeniem, ale również treścią jak i sposobem przekazywania dodatkowych informacji do serwera.

GET

Podstawowa metoda HTTP służąca do pobierania danych. Każde zapytanie o stronę internetową zaczyna się właśnie od tego żądania. Metoda GET służy do pobrania aktualnej wersji zasobu. W teorii powinno być ono idempotentne (zapamiętaj to słowo, ponieważ często pojawia się przy opisywaniu protokołu HTTP). Oznacza to, iż zapytanie GET pownno być bezstanowe. Czyli wysłanie wielu zapytań GET nie powinno wprowadzić zmian w pobieranym zasobie i za każdym razem powinno zwracać tą samą wersję strony (chyba, iż w między czasie zapytanie POST/PUT zmieniło jej stan). w uproszczeniu zapytania GET tylko pobierają dane, ale ich nie modyfikują.
Warto także zaznaczyć, iż zapytania typu GET nie posiadają ciała wiadomości, przez co dodatkowo informacje dotyczące przetwarzania zapytania przez serwer są dostarczane dzięki URLa, a dokładniej dzięki części nazwanej ?query. Pewnie nieraz spotkałeś się z adresem np. http://www.devkot.pl?search=Test. Część adresu URL, która zaczyna się od znaku zapytania to właśnie query, które pozwala przekazać dodatkowe informacje dla serwera w zapytaniach typu GET.
W tym miejscu warto też zaznaczyć, iż przeglądarki internetowe mogą zapisywać zapytania typu GET w pamięci podręcznej (cache). Inaczej mówiąc mogą być cachowane. Cache to mechanizm wbudowany w przeglądarkę, który jest wykorzystywany w celu zmniejszenia czasu odpowiedzi serwera. Bazuje on na zapisywaniu odpowiedzi serwera przez przeglądarkę. W przypadku gdy wyślemy dwa zapytania z rzędu dotyczące tego samego zasobu to wynik pierwszego może zostać zapisany w pamięci cache. Natomiast drugie zapytanie może wcale nie dotrzeć do serwera. Przeglądarka zamiast wysyłania zapytania do serwera może pobrać odpowiedź z pamięci podręcznej, ponieważ już wcześniej ją uzyskała.
Przykład zapytania GET:
> GET / HTTP/1.1 // {Czasownik HTTP} {Path} {Wersja Http} > Host: devkot.pl // Nazwa hosta > // Pusta linijka

POST

Metoda HTTP służąca do niejawnego wysyłania danych do serwera w celu utworzenia zasobu. Niejawne wysyłanie danych oznacza, iż nie są one przekazywane przez parametry URL tylko w ciele zapytania HTTP. W efekcie dane te w teorii powinny być bezpieczne. Są one jednak wysyłane jako czysty tekst w ciele zapytania np.
{"login":"mkotlarz","password":"password"}

Przesyłanie danych w formacie czystego tekstu jest niebezpiecznie, dlatego w większości portali wykorzystuje się protokół HTTPS, który odpowiada za zaszyfrowanie danych między klientem, a serwerem.

Przykład żądania POST:

> POST / HTTP/1.1 > Host: devkot.pl > Content-Type: application/json > Content-Length: 42 > {"login":"mkotlarz","password":"password"}

PUT

Żądania typu PUT służą do aktualizacji zasobu na serwerze, według specyfikacji mogą także służyć do ich dodawania. Oznacza to, iż jeżeli serwer wykryje, iż dany zasób istnieje to powinien go zaktualizować lub utworzyć tak aby jego wartości odpowiadały danym przesłanym w ciele żądania.
Główna różnica między POST, a PUT polega na tym, iż POST jest używany tylko i wyłącznie do tworzenia zasobów. Natomiast PUT może je także aktualizować.
Przykład:
> PUT / HTTP/1.1 > Host: devkot.pl/password > Content-Type: application/json > Content-Length: 42 > {"login":"mkotlarz","password":"password"}

DELETE

Żądania typu DELETE służą do usuwania zasobów. Odpowiedzi serwera na zapytania DELETE nie powinny zawierać ciała.
Przykład:
> DELETE /user/{1} HTTP/1.1 > Host: devkot.pl > // Pusta linijkaW specyfikacji HTTP znajdują się jeszcze inne metody/czasowniki HTTP. Polecam zapoznać się z resztą, ponieważ również mogą być przydatne. Więcej informacji o metodach możesz znaleźć tutaj: Metody HTTP

Odpowiedzi HTTP

Komunikacja wykorzystująca protokół HTTP bazuje na zapytaniach, wysyłanych przez klientów oraz odpowiedziach zwracanych przez klientów. Powyżej po krótce przedstawiłem czym są żądania, więc naturalnie skupimy się teraz na tym czym są odpowiedzi serwera. Podobnie jak w przypadku zapytania format odpowiedzi jest ściśle ustalony oraz składa się z:

  1. Linijki z wersją protokołu i kodem statusu odpowiedzi
  2. linijek zawierających nagłówki
  3. pustą linijkę oznaczającą koniec nagłówków
  4. ciało odpowiedzi (opcjonalne)

Przykład:

> HTTP/1.1 200 OK > Date: Tue, 27 Sep 2022 06:47:14 GMT > Content-Type: text/html; charset=UTF-8 > Transfer-Encoding: chunked > Connection: keep-alive > Server: Apache > Link: <https://www.devkot.pl/wp-json/>; rel="https://api.w.org/" > Link: <https://www.devkot.pl/>; rel=shortlink > Content-Encoding: gzip > > <!--Kod Html-->

Jak widać na powyższym przykładzie struktura odpowiedzi jest bardzo podobna do struktury zapytania. Różnice znajdują się w pierwszej linijce, gdzie nie występuje już czasownik HTTP oraz ścieżka do zasobu. Linijka ta składa się z wersji protokołu HTTP oraz kodu statusu odpowiedzi.

Statusy HTTP

Każda odpowiedź zwracana przez serwer musi posiadać informacje o statusie. Jest to podstawowa informacja o tym, czy dane zapytanie się powiodło. Kody statusów podzielone są na 5 różnych grup.

Status 1xx

Kody odpowiedzi zaczynające się od 100 oznaczają grupę informacyjną. Nie jest ona bardzo często wykorzystywana. Mimo wszystko uważam, iż warto wiedzieć o jej istnieniu. W ramach tej grupy wyróżnia się 4 najczęściej używane kody odpowiedzi:
kodStatus słownyZnaczenie
100ContinueProśba o dalsze wysyłanie zapytania
101Switching ProtocolsZmiana protokołu
110Connection Timed OutPrzekroczono czas połączenia. Serwer zbyt długo nie odpowiada.
111Connection refusedSerwer odrzucił połączenie

Status 2xx

Kody z grupy 2xx informują o tym, iż zapytanie zostało poprawnie wykonane przez serwer. W zależności od typu wykonywanej operacji kod odpowiedzi może jednak się różnić. Dla tej grupy można wyróżnić następujące kody:
kodStatus słownyZnaczenie
200OKZapytanie zostało wykonane poprawnie (najczęściej zwracany kod odpowiedzi). Powinno zwracać ciało wiadomości.
201CreatedZapytanie zostało wykonane poprawnie i zasób został utworzony
202AcceptedZapytanie zostało przyjęte do realizacji ale jego przetwarzanie jeszcze się nie skończyło.
204No ContentZapytanie zostało przetworzone, ale nie zwraca ciała wiadomości

Status 3xx

Ta grupa przekazuje informacje dotyczącego tego, iż zasób został przeniesiony w inne miejsce. Inaczej mówiąc informuje klienta o przekierowaniach zasobu. Po otrzymaniu odpowiedzi z grupy 3xx przeglądarki internetowe automatycznie wysyłają kolejne zapytanie HTTP pod adres otrzymany w odpowiedzi 3xx. Najczęśćiej wykorzystywanymi kodami z tej grupy są:

kodStatus słownyZnaczenie
301Moved PermanentlyInformuje klienta, iż zasób został przeniesiony na stałe pod nowy adres. Ten adres mam bardzo duże znaczenie w kontekście wyszukiwarek internetowych. Informuje on je o tym, iż strona która wcześniej była dostępna pod tym adresem została przeniesiona w nowe miejsce.
302FoundŻądany zasób został chwilowo przeniesiony pod nowy adres. W przyszłości powinien być ponownie dostępny pod adresem pierwotnym

Status 4xx

Ta grupa statusów zwraca informacje dotyczące błędów klienta. Odpowiedź tego typu oznacza, iż serwer nie był w stanie poprawnie obsłużyć żądania ze względu na błędne zapytanie. Jako błędne zapytanie należy uznać zapytanie wysłane pod nie istniejący adres URL. Błędne dane przekazane w ciele zapytania itp. Najczęściej spotykanymi odpowiedziami z tej grupy są:

kodStatus słownyZnaczenie
400Bad requestInformacja o błędnym zapytaniu. Bardzo często zwracana ze względu na źle przygotowane/brakujące dane przesyłane przez klienta. Informuje o tym, iż zapytanie takie nie będzie przetworzone.
401UnauthorizedInformuje o braku dostępu. Zapytanie wymaga uwierzytelnienia. zwykle zwracany w przypadku gdy dostęp do zasobów wymaga zalogowania użytkownika, ale dane autoryzacyjne nie zostały podane lub są niepoprawne.
403ForbiddenInformuje o braku uprawnień do zasobu. W odróżnieniu od kodu 401 dotyczy uprawnień danego użytkownika a nie samej autoryzacji,
404Not FoundOdpowiedź zwracana w przypadku gdy dany zasób nie istnieje

Warto przeczytać: Identyfikacja, uwierzytelnianie, autoryzacja – czym się różnią i dlaczego są ważne?

Status 5xx

Ostatnią grupą statusów są te związane z błędami w przetwarzaniu po stronie serwera. Najczęściej spotykanymi są:

kodStatus słownyZnaczenie
500Internal Server ErrorInformuje klienta o tym, iż wystąpił problem z przetwarzaniem po stronie serwera.
502Bad GatewayPortal internetowy może składać się z wielu węzłów, które będą odpowiedzialne za przekazanie zapytania do serwera, który będzie finalnie odpowiedzialny za przetwarzanie zapytania. Odpowiedź ze statusem 502 informuje klienta o tym, iż jeden z tych pośredników otrzymał błędną odpowiedź. W wyniku czego przetwarzanie musiało zostać przerwane.
503Service UnavailableInformuje klienta o tym, iż serwer który powinien obsłużyć zapytanie jest przeciążony/niedostępny.

Podsumowanie

Dziś kolejny artykuł przedstawiający teorię związaną z działaniem internetu. Omówiliśmy sobie jeden z najważniejszych protokołów wykorzystywanych w pracy programisty, czyli protokół HTTP. Bardzo ważne, abyś zrozumiał zasady jego działania, ponieważ jako programista internetu bardzo często będziesz z niego korzystał. Dobre zrozumienie HTTP ułatwi Ci pracę.

Mam nadzieję, iż lektura Ci się podobała i do zobaczenia w kolejnych artykułach, gdzie coraz bardziej będziemy zbliżać się samego programowania.

W kolejnym artykule postaram Ci się przybliżyć aspekt bezpieczeństwa w sieci.

Do zobaczenia w kolejnych postach!

Idź do oryginalnego materiału