HTTP - Na tym opiera się internet - Programowanie jest łatwe

Mówi się, że internet to World Wide Web, inaczej WWW czy W3. Naturalnie jest to błędne uproszczenie, jednak to wystarczy, aby zacząć podróż po bezkresie cyberprzestrzeni.

Źródło: internety

Zarys historyczny

WWW to idea, polegająca na ogólnodostępnym i swobodnym dostępie do informacji. W zamyśle było stworzenie struktury do udostępniania tzw. dokumentów hipertekstowych za pomocą tzw. hiperlinków. Teraz znamy to po prostu jako strony internetowe i linki do nich, jednak na początku lat 90-tych XX. wieku była to całkowita abstrakcja - wytłumacz to swojej prababci...

Dokumentami ongiś były zwykłe pliki tekstowe, dostępne przeważnie w środowiskach naukowych lub wielkich korporacjach. Dla zwiększenia czytelności stworzono specjalny “język” opisu dokumentów tak, aby treści w tych dokumentach były bardziej czytelne. Stąd skrót HTML (Hypertext Markup Language). Taki hiperdokument posiadał, poza znacznikami określającymi nagłówki, tabele i inne znaczniki do formatowania tekstu, hiperłącza czyli linki do innych dokumentów. Rdzeniem WWW, w mojej opinii, jest protokół, który odpowiada za transmisję danych w ramach WWW, czyli tytułowy HTTP- Hypertext Transfer Protocol. Pierwsza wersja oznaczona jako HTTP/0.9 była prostym protokołem do wysyłania „surowych” (tekstowych) danych przez Internet.

Charakterystyka

Jak działa ów protokół? Otóż realizuje on architekturę klient - serwer i to w dodatku bezstanową. Komunikacja polega na tym, że jedna końcówka (klient) wysyła zapytanie o zasoby do drugiej końcówki (serwera). Po odebraniu zapytania serwer odpowiada albo danymi, które stanowią przedmiot zapytania, albo błędem. Komunikacja zawsze odbywa się w ten sposób. Czyli za każdym razem nawiązywane jest połączenie do serwera, następnie klient wysyła swoje zapytanie (żądanie) po czym otrzymuje odpowiedź.

Komunikacja przy użyciu tego protokołu działa na zasadzie żądanie-odpowiedź w architekturze „klient-serwer”. Klient (zazwyczaj przeglądarka internetowa, jednakże na może nim być każda aplikacja) wysyła specjalnie przygotowany nagłówek z danymi (żądanie) i wysyła go do serwera. Po odebraniu żądania serwer analizuje dane, a następnie generuje odpowiedź – wysyła odpowiednio przygotowany nagłówek odpowiedzi, a następnie (jeżeli występują) dane, które zażądał klient. Po tym kanał komunikacji jest zamykany. Serwer nigdy nie wysyła żadnego zapytania do klienta.

Bezstanowość polega na tym, że ani klient ani serwer nie zachowują połączenia po wymianie danych. Nawet po ponownym zestawieniu połączenia serwer nie wie, że połączył się do niego ponownie ten sam klient. Tutaj mała uwaga. Protokół jest bezstanowy i w pierwszej wersji zamykał połączenie po szczęśliwej wymianie danych pomiędzy klientem a serwerem. Od wersji 1.1 zmieniła się ta druga rzecz i kanał komunikacji (czytaj niżej) może pozostać otwarty, aby obsłużyć kolejne zapytania od tego samego klienta (np. gdy klient żąda szeregu plików graficznych, które są umieszczone w dokumencie hipertekstowym). Jeżeli chodzi o identyfikację klienta, np. po zalogowaniu się na jakimś portalu - tutaj sprytnie użyto możliwości nagłówka HTTP w celu umieszczenia tam? Kto zgadnie? Odpowiedź 2 rozdziały niżej.

Nadmienię, że jest to protokół tekstowy, to znaczy, że można posługiwać się nim za pomocą klawiatury i (dosłownie) napisać komunikację między klientem a serwerem, co zademonstruję poniżej.

Naga prawda

Jak ustanawiane jest połączenie pomiędzy końcówkami? Otóż to jest miejsce, w którym król jest nagi i wychodzi na to, że to nie HTTP czy WWW jest internetem. Prawdziwym internetem jest… Protokół TCP/IP. TCP/IP to internet ale szerzej opiszę to w innym artykule. Teraz musisz przyjąć to jako dogmat ale nie zostawię Ciebie z takim niedosytem. Protokół TCP/IP składa się z dwóch współpracujących ze sobą protokółów. TCP to Transmission Control Protocol czyli protokół transmisji danych, który odpowiada za to, aby wysłane dane dotarły w takiej samej postaci, w jakiej zostały wysłane. IP natomiast, pewnie bardziej znane, odpowiada za adresowanie uczestników komunikacji. Każda końcówka posiada swój unikalny adres, za pomocą którego jest identyfikowana. Wyobraź to sobie jako linię telefoniczną, w której każdy ma swój numer telefonu, a za transmisję odpowiada specjalnie nadawany sygnał. HTTP jest protokołem warstwy aplikacji. Korzystając z porównania powyżej, HTTP byłby w tym przypadku np. alfabetem Morse’a.

HTTP od kuchni

Każde zapytanie składa się z dwóch części. Pierwszą jest nagłówek zapytania (albo odpowiedzi), który używany do opisu/charakterystyki samego zapytania, a drugą są dodatkowe pola precyzujące naturę zapytania. W nagłówku znajdują się takie informacje jak wersja protokołu, adres zasobu, o który się rozchodzi, rodzaj zapytania, informacje o kliencie, rodzaje obsługiwanych zasobów czy informacje sterujące zachowaniem samej komunikacji. Jego budowa wygląda następująco: na początku występuje linia żądania, w której umieszczany jest metoda (rodzaj zapytania), ścieżka do zasobu oraz informacja o wersji używanego protokołu. Metodami mogą być GET, PUT, POST, DELETE, odpowiednio do pobrania/wyświetlenia zasobu (GET), aktualizacji istniejącego (PUT), stworzenia nowego (POST) czy usunięcia istniejącego (DELETE). Celowo umieściłem tylko te metody (jest ich więcej), ponieważ te realizują tzw. CRUD, czyli architekturę, która umożliwia tworzenie, odczyt, modyfikację i usuwanie zasobów (Create, Read, Update, Delete), która jest wykorzystywana w bezstanowych API- w serwisach internetowych, aplikacjach mobilnych.

Poza tym nagłówek posiada dodatkowe linie (tzw. pola nagłówka), które uzupełniają/precyzują dokładnie żądany zasób i przekazują informacje serwerowi, aby ten mógł lepiej obsłużyć zapytanie. W tych liniach znajdują się dane o kliencie (np. nazwa programu, która wykonuje zapytanie), adresie serwera, na który zostało wysłane zapytanie czy o obsługiwanych formatach danych.

Oto przykładowy nagłówek, który wysyła przeglądarka internetowa (klient) do serwera, gdy chcemy wyświetlić główną stronę Facebook’a:

GET / HTTP/1.1
Host: facebook.com
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
Accept-encoding: gzip, deflate, br
Accept-language: en-US,en;q=0.9,pl;q=0.8
Cookie: datr=6snDWVk_QKFr08JXyjuCgDBr; 
User-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.84 Safari/537.36

Krótkie omówienie powyższego:

W odpowiedzi otrzymamy coś takiego:

HTTP/1.1 301 Moved Permanently
Location: https://facebook.com/
Content-Type: text/html; charset="utf-8"
X-FB-Debug: oiy1CeCskh65ILEXereoXrASNwa5Yd1T/rKcWe/sS7U8xx9zujaSVyGFOqzSPZ7rVpcRx/yMIXesKQkokc6H4g==
Date: Tue, 09 Jan 2018 20:38:52 GMT
Connection: keep-alive
Content-Length: 0

Wygląda to podobnie jak zapytanie, jednak różni się przede wszystkim pierwszą linią. Linia odpowiedzi najpierw informuje o zgodności wersji protokołu. Następnie przekazywany jest kod odpowiedzi oraz opis słowny. W tym przypadku jest to informacja “przekierowano na stałe” czyli wysyłając to zapytanie powinienem zawsze odpytywać adres, podany w linii “Location”. Tutaj serwerowi chodzi o to, że powinienem korzystać z szyfrowanego połączenia HTTPS (S na końcu od Secure). Dalsze pola nagłówka przedstawiają kolejne informacje, które mogą okazać się przydatne albo nie.

Tutaj kilka uwag. Poza opisanymi w standardzie HTTP polami jak Location, Host, etc., protokół dopuszcza umieszczanie dowolnych pól o dowolnej nazwie i wartości. Np. Facebook umieszcza w odpowiedzi “X-FB-Debug” z jakąś podejrzaną wartością- nie jest to standardowe pole HTTP. Ty, jeżeli chcesz, również możesz dodać dodatkowe pola w zapytaniu do serwera. Serwer je po prostu zignoruje. Jest to przydatne, gdy np. to my odpowiadamy za przetwarzanie zapytania po stronie serwera. Ma to miejsce, tworząc backend. Tak samo działa to w drugą stronę, gdy zajmujemy się frontendem. Każda linia zapytania oddzielona jest znakiem nowej linii (a będą ścisłym, dwoma bajtami CRLF). zapytanie zakończone jest dwoma nowymi liniami (czyli 2x CRLF).

Z palca

Z powyższego wynika, że zapytania HTTP można pisać samemu np. w notatniku. W jaki sposób wysłać takie zapytanie? Otóż wystarczy do tego program [telnet](), który jest dostępny w każdej szanującej się powłoce, np. wiersz poleceń Windows. Telnet przyjmuje dwa parametry: adres oraz port na jaki ma się połączyć. Adres jest domeną lub adresem IP serwera, który ma obsłużyć zapytanie. Standardowym portem, który wykorzystuje HTTP to port nr 80 (443 dla połączeń HTTPS). Z tymi parametrami telnet nawiąże połączenie za pomocą protokołu TCP/IP, który umożliwi nam transmisję danych HTTP. Kontynuując nasz przykład z Facebookiem, po uruchomieniu wiersza poleceń wystarczy uruchomić polecenie

telnet facebook.com 80 A następnie przepisać/wkleić zapytanie, które nas interesuje i potwierdzić dwukrotnie enterem. W odpowiedzi dostaniemy nagłówek jak w przykładzie powyżej. Aby było ciekawiej, polecam zabawę z serwerem, który nie wymaga szyfrowanego połączenia. Np. serwis meteo.pl. Zapytanie do tego serwisu w wersji minimum mogłoby wyglądać następująco: telnet meteo.pl 80

Wraz z nagłówkiem:

GET / HTTP/1.1
Host: www.meteo.pl

W odpowiedzi otrzymamy mniej więcej:

HTTP/1.1 200 OK
Date: Tue, 09 Jan 2018 21:22:14 GMT
Server: Apache/2.2.3 (Linux/SUSE)
X-Powered-By: PHP/5.2.0
Pragma: no-cache
Set-Cookie: METEO_PL=a%3A4%3A%7Bi%3A%22WWW_METEO_PL%22%3Bi%3A2%3A0%3B%7D; expires=Sun, 18-Jun-2034 21:22:20 GMT; path=/
Transfer-Encoding: chunked
Content-Type: text/html
…

Jak widać, serwis meteo.pl podaje nam ciasteczko za pomocą “Set-Cookie”. Po ostatniej linii nagłówka znajdzie się strona HTML podzielona na kawałki (ponieważ serwer wysłał dane w kawałkach Transfer-Encoding: chunked). Zachęcam do samodzielnej zabawy z różnymi serwisami. Internet bez przeglądarki wygląda nieco inaczej, prawda?

Sesja telnet do serwisu meteo.pl

HTTP to nie tylko przeglądarka

Jak widać z powyższego, protokół jest na tyle prosty w obsłudze, że można go czytać bez użycia programów. Pomimo wielu opcji i ogromnej funkcjonalności, prostota implementacji tego protokołu (niektórzy robią to za pomocą 30 bajtów) pozwala na swobodne umieszczanie go w niemalże każdym oprogramowaniu. To przyczyniło się do jego popularności. To właśnie ta cecha sprawiła, że jest on używany jako podstawowy środek wymiany danych pomiędzy końcówkami w sieci.

Inne zabawki

Przeglądarki to bardzo rozbudowane twory. Nie chodzi mi tutaj o funkcje i możliwości, które oferują, ale narzędzia, w jakie są wyposażone. Każda szanująca się przeglądarka posiada zestaw narzędzi dla programistów (w szczególności frontend developerów), które w ciągu ostatnich kilku lat mocno się ustandaryzowały i niemalże w każdej przeglądarce zachowują się podobnie. Odnajdź w przeglądarce, z której teraz korzystasz “narzędzia dla programistów”- zazwyczaj po kliknięciu prawym przyciskiem myszy i wybraniu opcji “zbadaj element” ale są też inne sposoby na ich otwarcie. Za ich pomocą, poza analizą struktury strony, na której się znajdujesz, możesz zbadać wszystkie zasoby (pliki), które są transferowane pomiędzy Tobą a serwerem. Możesz podejrzeć także nagłówki HTTP, które sa używane do ich transmisji. Ogólnie sporo frajdy- popsuj coś!

Web inspector w Google Chrome

Wersja dwa zero

W roku 2015 konsorcjum zdecydowało się na wprowadzenie do standardu nowszej wersji HTTP pod nazwą HTTP/2 (2.0 się nie przyjęło). Nowy “internet” (bo, o zgrozo, tak był komentowany swego czasu) umożliwia np. wysyłanie wielu plików w jednym strumieniu zapytania (tj. Serwer odpowiadając stroną HTML wysyła także wszystkie pliki przez nią wymagane), kompresuje nie tylko dane ale także nagłówki HTTP (tutaj ciekawostka, to zagadnienie było przedmiotem mojej pracy magisterskiej :-)) oraz “stawia na bezpieczeństwo” czyli z definicji korzysta z szyfrowanego połączenia, co jest kwestią sporną - niby standard tego nie wymaga, jednak implementacja HTTP/2 w przeglądarkach już tak.

Posłowie

Tak rysuje się “internet”, a raczej jego składowa część. Temat jest obszerny, ale czego się spodziewać po tak potężnym narzędziu, bez którego np. moje życie nie miałoby sensu… Nie musisz znać wszystkich szczegółów i umieć rozmawiać z serwerami, pisząc na klawiaturze zapytania HTTP. Grunt to znać ogólną zasadę działania, aby lepiej zrozumieć zagadnienia z tym związane, które są w szczególności przydatne, gdy programujemy serwisy internetowe czy aplikacje, które komunikują się z backendem.

Dodano: 2018-01-09 10:21 przez Piotr Poźniak

słowniczek , http , html , internet , www , klient , serwer , tcp/ip ,
Piotr Poźniak
O autorze:

Programuję od ponad 15 lat. Prowadzę software house. Angażuję i zachęcam wszystkich do programowania w ramach inicjatywy Programowanie jest łatwe.