Żądanie HTTP, czyli co stoi za komunikacją WWW

14.08.2018 / / Developers

Podczas pracy z PHP (a przynajmniej na początku swojej przygody z tym językiem) w zasadzie nie jest konieczne zrozumienie sposobu przesyłania informacji protokołem HTTP. Mechanizmy dostępne w PHP właściwie zajmują się za nas całą komunikacją. Nie oznacza to, że nie napotkamy na swojej drodze programistycznej, np. potrzeby dokładniejszego sterowania nagłówkami. Rozumienie zasad działania protokołu HTTP w przypadku web deweloperów na pewno nie zaszkodzi, a prawdopodobnie pomoże. Ważne może stać się również zrozumienie różnic pomiędzy HTTP 1.1 oraz HTTP 2, co w bezpośredni sposób przyczynia się do zmiany UX dla naszych odbiorców. Spróbujmy więc wgryźć się w głąb tego mechanizmu.

Skąd wziął się pomysł na przesyłanie treści tekstem?

We wczesnych latach Internetu i protokołów komunikacji, informacje były przekazywane przez podstawowy ciąg informacji (np. 8-bitowych) o ustalonej strukturze. Każdy z użytkowników musiał studiować dokumentację, aby wiedzieć, że dany ciąg oznacza taki lub inny stan. Wprowadzenie ustandaryzowanej struktury/kodowania tekstu znacząco przyspieszyło rozwój protokołów komunikacji. W dzisiejszych czasach nawet mimo kilku obowiązujących standardów kodowania znaków (np. UTF-8 czy ISO 8859-2), dużo łatwiej jest skorzystać z uniwersalnego słownika, a następnie odczytać odpowiednie wartości z zapytania, w celu właściwego obsłużenia tego po stronie klienta i serwera. Gdyby taki standard nigdy nie powstał, prawdopodobnie tworzenie aplikacji w różnych technologiach, korzystających z różnych rodzajów kodowania znaków, praktycznie by nie istniało. Problemy z mapowaniem znaków byłyby tak duże, że gra nie byłaby warta świeczki.

Z czego składa się żądanie i odpowiedź HTTP(s)

Jeden obraz jest wart więcej niż tysiąc słów, dlatego dla lepszego zobrazowania komunikacji, o której mowa, poniżej znajdziecie jej wizualizację. Zapoznajcie się z nią, a następnie wspólnie przejdziemy przez proces obsługi żądania krok po kroku.

Schemat HTTP

Jak przebiega cały proces obsługi żądania?

  1. DNS Lookup:

    a. Klient wysyła żądanie DNS Query do serwera DNS (np. dostawcy internetu lub ogólnodostępnego DNS-a jak 8.8.8.8 od Google),

    b. DNS zwraca adres IP dla hosta widocznego w DNS Query (np. dla adresu www.x-coding.pl dostajemy IP 136.243.73.152).

  2. Ustanowienie połączenia TCP:

    a. Klient wysyła pakiet SYN,

    b. Serwer wysyła pakiet SYN-ACK,

    c. Klient odpowiada pakietem ACK.

Ustanowienie połączenia TCP

  1. Wysłanie żądania HTTP.

  2. Oczekiwanie na odpowiedź serwera.

  3. Odebranie pierwszego pakietu z serwera.

  4. Odebranie drugiego segmentu TCP z flagą PSH (push — informacja w protokole, że dane należy przesłać dalej do aplikacji, zamiast buforować).

  5. Klient odpowiada pakietem ACK co drugi segment z serwera

  6. Po odebraniu danych klient wysyła pakiet FIN do zakończenia połączenia TCP.

W przypadku HTTP 1.1 domyślnie stosuje się Persistent HTTP Transactions -— pozwala to na pominięcie kroku 2. W HTTP 1.0 też możliwe jest używanie trwałego połączenia TCP, ale wymusza się to poprzez nagłówek Keep Alive.

Przykłady i objaśnienie nagłówków

Wiedza, do czego służą poszczególne nagłówki i jak je można wykorzystać, na pewno się przyda -— niejednokrotnie oszczędzi bólu głowy i googlowania. Kilka wybranych omówimy poniżej, a dla Waszej wygody załączamy także link do pełnej listy

Jest dość rozbudowana i można znaleźć ją tutaj: https://pl.wikipedia.org/wiki/Lista_nag%C5%82%C3%B3wk%C3%B3w_HTTP

Nagłówki żądania

Cookie – przesyłane są ciasteczka, które zostały ustawione w przeglądarce. Ciasteczka są najczęściej wykorzystywane jako identyfikator (np. podczas logowania), dzięki czemu użytkownik nie jest zmuszony do udzielania tych samych informacji podczas kolejnych wizyt

User-Agent – nagłówki wykorzystywane podczas budowania statystyk odwiedzin naszej witryny, identyfikują rodzaj przeglądarki i roboty

Host – nagłówek służący do stawiania wielu witryn na jednym serwerze

X-Requested-With – jest to definicja wszystkich dodatkowych elementów wysłanych wraz z zapytaniem. Najczęściej stosuje się ją do przekazywania cookiesów pomiędzy serwerem a klientem, np. do realizacji autoryzacji użytkownika lub reklam kierowanych.

Accept-Language – określa język przeglądarki i wyświetla treść adekwatną do zapytania

Nagłówki odpowiedzi

Allow – nagłówek określający jakie rodzaje żądań obsługuje serwer (GET/.POST/DELETE/PUT)

Content-Type – dzięki temu nagłówkowi zostajemy poinformowani o formacie i stronie kodowej wysłanej odpowiedzi

Content-Length – określa w bitach długość zapytania. Służy do to tego, aby odbiorca zapytania mógł sprawdzić czy otrzymał całe zapytanie i czy zostało wysłane poprawnie.

Expires – nagłówek określający deadline, datę po której wskazany dokument nie będzie aktualny

Location – nagłówek wymuszający przekierowanie na dany adres

Set-Cookie – nagłówek przekazujący przeglądarce ustawienia określonych plików Cookie

Transfer-Encoding – określa przekazanie zawartości dokumentu. Metody przekazywania dzielimy na:

  • chunked — przesyłanie zawartości kawałkami
  • identity — tekst nieskompresowany
  • gzip — dane skompresowane algorytmem DEFLATE
  • compress — dane skompresowane algorytmem LZW

Różnice między HTTP 1.1 i HTTP 2

Wpływ użycia HTTP2 na wrażenia użytkownika można zobaczyć na stronie: http://www.http2demo.io/.

Protokół HTTP 1.1 pojawił się jako draft w październiku 1997 roku, a w czerwcu 1999 był już w wersji RFC 2616, czyli obowiązującym do dzisiaj standardzie. Prawie 20 lat, jakie upłynęło od tego czasu, dało o sobie znać i obecnie największymi ograniczeniami, jakie wiążą się z używaniem HTTP 1.1, są:

  • jedno żądanie na jedno połączenie TCP — przeglądarki radzą sobie z tym, ustanawiając kilka jednoczesnych połączeń (ich maksymalna liczba zależy od przeglądarki),

  • konieczność powtarzania wielu nagłówków HTTP przez każde żądanie, co przy wielu żądaniach wprowadza spory narzut komunikacyjny.

W protokole HTTP 2 mamy natomiast kilka ciekawych elementów znacząco poprawiających wrażenie użytkownika:

  • kilka równoległych żądań na jednym połączeniu TCP,
  • skompresowane nagłówki,
  • możliwość wysyłania przez serwer do klienta danego zasobu od razu (push), zamiast czekać na jego żądanie (np. na plik CSS czy JS).

Zobaczcie porównanie wczytywania strony HTTP 1.1 i HTTP 2 od strony zasobów: HTTP 1.1: https://cdn-images-1.medium.com/max/800/1*vrnd4kqNzvhHh8n0DcfWOQ.png HTTP 2: https://cdn-images-1.medium.com/max/800/1*t3v3lEP7V3jG3hYCx65m_w.png

Mam nadzieję, że po lekturze tego artykułu trochę lepiej rozumiecie znaczenie poszczególnych nagłówków, oraz różnice między HTTP 1.1 i HTTP 2. Jeśli jednak wciąż coś jest dla Was niejasne — nie wahajcie się zadać pytania w komentarzu.