Протоколът HTTP

HTTP представлява прост текстов протокол, който се използва от услугата WWW за осигуряване на достъп до практически всякакъв вид данни, наричани събирателно ресурси. В HTTP протокола има понятия като клиент (обикновено това са Web-браузърите) и сървър (това са Web-сървърите). Обикновено HTTP протоколът работи върху стандартен TCP сокет отворен от клиента към сървъра. Стандартният порт за HTTP протокола e 80, но може да се използва и всеки друг TCP порт. Комуникацията по HTTP се състои от заявка (request) – съобщение от клиента към сървъра и отговор (response) – отговор на сървъра на съобщението от клиента.

В развитието си HTTP протоколът е преминал през версиите 0.9, 1.0 и 1.1, която е най-разпространена. На практика когато се говори за HTTP, обикновено се има предвид HTTP 1.1.

HTTP заявки

HTTP заявката при версия 1.1 на протокола има следния формат:

Code:
<метод> <Request-URI> HTTP/1.1
<header-полета>
<празен ред>



HTTP заявките имат 3 основни елемента: метод, Request-URI и header-полета.
Методът описва вида на HTTP заявката, изпратена от клиента. Най-често използваните методи са GET и POST. Чрез GET клиентът изисква някакъв ресурс от Web сървъра. POST служи за предаване на данни към сървъра и извличане на ресурс. Имената на методите в HTTP заявките се изписват винаги с главни букви.

Идентификаторът Request-URI определя ресурса, над който ще оперира заявката. В частта Request-URI могат да се използват два вида идентификатори:
- URI идентификатор (Uniform Resource Identifier)
- релативен път спрямо главната директория на Web-сървъра

Един URI идентификатор може да бъде или URL адрес (Uniform Resource Location, например http://www.nakov.com/inetjava/index.html), т.е. да е идентификатор на ресурс, зададен чрез уникалното си местоположение или URN име (Uniform Resource Name, например urn:isbn:954-8905-06-X), т.е. да е идентификатор на ресурс, зададен чрез уникалното си име по даден URN namespace идентификатор (за нашия пример това е идентификатора isbn). В практиката URN схемата за идентификация на ресурс почти не се използва при HTTP заявки.

Релативният път спрямо главната директория на Web-сървъра задава местоположението на ресурс в рамките на текущия Web-сървър. Това е частта от URL, която стои след името на хост-а (сървъра) в URL идентификатора. Например един такъв релативен път може да бъде идентификаторът /inetjava/index.html.

Фрагментът HTTP/1.1 с който завършва първият ред на HTTP заявката задава версията на HTTP протокола, която ще бъде използвана.

Header-полетата от заглавната част задават допълнителни параметри на заявката и определят различни изисквания относно ресурса, който се очаква да бъде върнат от Web-сървъра.

Празният ред определя края на заявката.

Примерна HTTP заявка

Да дадем един пример за HTTP заявка, която връща началната страница от сайта http://www.dir.bg/ :

Code:
GET / HTTP/1.1
Host: www.dir.bg
[празен ред]



Как се отличават виртуалните хостове на един Web-сървър

На един Web-сървър може да има хостнати няколко различни сайта, които могат да започват с различни Интернет имена. Такива сайтове се наричат виртуални хостове в рамките на Web-сървъра. Например сайтовете с URL адреси http://www.nakov.com/ и http://bgcon.org/ могат да са хостнати в Web-сървъра на една и съща машина, да кажем машината с IP адрес 194.12.244.90. Възниква въпросът как браузърът указва кой от двата адреса иска, след като те се обслужват от един и същ Web-сървър на една и съща машина.

Ясно е, че в услугата DNS Интернет имената http://www.nakov.com/ и bgcon.org трябва да са регистрирани да съответстват на IP адреса 194.12.244.90. Когато в полето за адрес на един стандартен Web-браузър се напише един от горните два URL адреса, да кажем http://www.nakov.com/, браузърът прави следното: Първо чрез услугата DNS получава IP адреса на машината, която хоства търсения сайт (www.nakov.com). След това отваря TCP връзка към тази машина на порт 80 и изпраща заявка за извличане на ресурса "/". В хедъра на тази заявка браузърът указва в полето Host стойността http://www.nakov.com./ Именно по това поле Host в хедъра на HTTP заявката Web-сървърът разбира за кой от всички виртуални хостове се отнася тази заявка.

Другият начин при HTTP заявка да се укаже виртуалният хост в Web-сървъра е да се използва URI идентификатор на искания ресурс (URL адрес). В този случай името на хоста се включва в самия този идентификатор.

Методи на HTTP заявката

Протоколът HTTP версия 1.1 поддържа общо 8 различни метода: GET, POST, HEAD, PUT, DELETE, OPTIONS, TRACE, CONNECT. Най-често използваните методи са GET и POST и те имат най-голямо значение за Web-програмирането.

HTTP GET заявки

GET методът представлява команда за извличане на ресурс, указан от зададено URI или релативен път в рамките на Web-сървъра. Всичко, което прави Web-сървърът за извличането на статичен ресурс чрез GET заявка е да го прочете от файловата система и да го върне на клиентите в подходящ HTTP отговор. При извличане на динамичен ресурс сървърът изпълнява програмния код, който генерира ресурса и връща резултата от него в HTTP отговор. Ето един реален пример за HTTP заявка с GET метод:

Code:
GET /InetJava-2002-program.html HTTP/1.1
Host: inetjava.sourceforge.net	
Accept: */*
Accept-Language: bg
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/4.0(compatible;MSIE 6.0; Windows NT 5.0)
Connection: Keep-Alive
Cache-Control: no-cache
[празен ред]



Изпращането на тази заявка към Web-сървъра, който слуша на порт 80 на машината с Интернет адрес inetjava.sourceforge.net, ще върне файла InetJava-2002-program.html от директорията на виртуалния хост inetjava.sourceforge.net.

Тази заявка e съвсем истинска. Тя е генерирана от Web-браузъра Internet Explorer 6.0 при опит да се отиде на URL адрес http://inetjava.sourceforge.net/InetJava-2002-program.html и е прихваната чрез софтуер за подслушване на мрежовия трафик.

При HTTP GET заявката ако към искания ресурс трябва да се зададат параметри, това става като към URI-то се добави въпросителен знак, а след него двойки от вида <име на параметър>=<стойност>, като двойките от този вид се разделят една от друга със &. За избягването на някои непозволени символи се използва така нареченото URL-кодиране, за което ще стане дума по-нататък.

HTTP POST заявки

POST методът служи за изпращане на данни от клиента към Web-сървъра. Обикновено сървърът предава получените от POST заявката данни на някакъв CGI скрипт или вграден модул за динамично генериране на HTML, който ги обработва и връща някакви резултати. Тези резултати се връщат на клиента като отговор на неговата заявка. Ето един реален пример за HTTP заявка с POST метод, изпратена от Internet Explorer 6.0 при опит за влизане в Web-базираната система за електронна поща на адрес http://www.abv.bg/ :

Code:
POST /webmail/login.phtml HTTP/1.1
Host: http://www.abv.bg/
Accept: */*
Accept-Language: bg
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/4.0(compatible;MSIE 6.0; Windows NT 5.0)
Connection: Keep-Alive
Cache-Control: no-cache
Content-Length: 59
[празен ред]
LOGIN_USER=boris
DOMAIN_NAME=abv.bg
LOGIN_PASS=tajnamajna
[празен ред]



Както се вижда, параметрите се предават след самата заявка, като в header-полетата се указва общата дължина в символи на всички параметри и техните стойности (заедно със символите за край на ред). За разделител между header-полетата и параметрите се използва празен ред. За край на заявката се използва също празен ред. Ако параметрите съдържат непозволени символи, те се кодират по специален начин. Кодирането на параметрите и стойностите им се прави автоматично от Web-браузъра, а разкодирането им съответно от скрипта, който обработва заявката на Web-сървъра.

Отговори на HTTP заявки

На всяка HTTP заявка, независимо дали е валидна или не, Web-сървърът връща някакъв отговор. При валидна заявка за съществуващ ресурс Web-сървърът връща този ресурс, а в противен случай връща код на грешка заедно с текстово описание защо се е получила. Отговорът на HTTP заявка има следния формат:

Code:
HTTP/1.1 <код> <текст>
<header-полета>
<празен ред>
<ресурс>



Първият ред се нарича статус линия и съдържа версията на HTTP протокола, по който се изпраща отговора, трицифрен код на резултата или код на грешка и кратко текстово описание на този код.

Следват header-полетата. Те съдържат различни параметри на върнатия ресурс, както и информация за Web-сървъра.

Следва празен ред, а след него ресурсът, кодиран по описания в header-полетата начин. В зависимост от типа на ресурса, сървърът може да го върне кодиран по различен начин и по различен начин да укаже на клиента колко байта е дълъг HTTP отговорът.

Стойностите на header-полетата и формата на ресурса са от интерес основно за Web-браузъра и затова няма да ги разглеждаме в детайли.

Основното, което трябва да знаем, е че на всяка HTTP заявка сървърът отговаря с HTTP отговор, който съдържа искания ресурс или грешка. Кодовете на грешките започват с цифрата 4 или 5. Кодовете за успешен резултат започват с 2, а кодовете, носещи специална информация – с 3. Най-често срещаните кодове при HTTP отговор са: 200 – успех; 304 – документът не е променян от времето, зададено в header-а (използва се от браузърите при кеширане на документи); 404 – ресурсът не е намерен; 500 – грешка на сървъра. Ето един цялостен пример за изпращане на HTTP заявка за извличане на главната страница от локално стартиран Web-сървър и отговорът на тази заявка:

Code:
C:\> telnet localhost 80
GET / HTTP/1.1
Host: localhost
[празен ред]
HTTP/1.1 200 OK
Date: Sat, 10 Aug 2002 16:09:18 GMT
Server: Apache/1.3.9 (Win32)
Accept-Ranges: bytes
Content-Length: 73
Content-Type: text/html
[празен ред]
<html>
<head> <title> Test </title> </head>
    Test HTML page.
</html>



Както се вижда, сървърът е върнал отговор на HTTP заявката с код 200 (успех) и е върнал искания ресурс. Ето и един пример за неуспешно завършила заявка:

Code:
C:\> telnet localhost 80
GET /img/nakov.gif HTTP/1.0
[празен ред]
HTTP/1.1 404 Not Found
Date: Sat, 10 Aug 2002 16:20:17 GMT
Server: Apache/1.3.9 (Win32)
Connection: close
Content-Type: text/html
[празен ред]
<HTML><HEAD>
<TITLE>404 Not Found</TITLE>
</HEAD><BODY>
<H1>Not Found</H1>
The requested URL /img/nakov.gif
was not found on this server.<P>
<HR><ADDRESS>Apache/1.3.9
Server at test Port 80</ADDRESS>
</BODY></HTML>



Вижда се, че сървърът освен че връща в отговор на заявката код на грешка 404 изпраща и допълнителна информация, която пояснява значението на този код. Тази информация е във вид на HTML документ, защото е предназначена да бъде показана в браузъра на клиента, който е поискал липсващия ресурс.

Вероятно сте забелязали, че в последния пример използваме заявка по протокол HTTP/1.0, а в предходния – по HTTP/1.1. Най-съществената разликата между двете версии на протокола е, че при HTTP/1.0 след връщането на отговора на HTTP заявка сървърът веднага затваря сокета с клиента, а при HTTP/1.1 може с едно отваряне на сокет да се изпълнят последователно няколко HTTP заявки. Това прави HTTP/1.1 протокола по-бърз заради което е предпочитан от повечето HTTP клиенти.