Протокол HTTP 1.1 расширяет возможности предыдущей версии и добавляет виртуальные хосты. Сейчас мы посмотрим, для чего это нужно, и как это работает.
Предыдущая версия требует наличия только request line. В ней мы описываем, какой путь на сайте мы хотим посмотреть. Но упоминания сайта как такового здесь нет. При этом мы подключаемся по telnet к конкретному IP адресу. Отсюда можно сделать вывод, что понятие домена (доменного имени) при использовании HTTP 1.0 неважно. Действительно, эта версия была создана в те времена, когда считалось, что один IP адрес соответствует одному сайту. Естественно, это не могло продолжаться долго, потому что рост интернета был стремительным. И HTTP 1.1 ввел такое понятие как виртуальные хосты. С точки зрения реализации в протоколе HTTP появилась одна небольшая деталь. Кроме request line стал обязательным еще и заголовок, который называется host. Он определяет, какой именно домен должен быть возвращен с этого IP адреса.
HEAD / HTTP/1.1
host: hexlet.io
На самом деле, иногда в поведение HTTP и серверов заложены какие-то умолчания, например, они могут исправлять ошибки пользователей. То есть можно сделать запрос HTTP 1.1 без указания хоста и получить что-то в ответ. По-хорошему такой запрос вообще не должен проходить, но часто веб-серверы отдают сайт, который указан в настройках по дефолту. Например, в Nginx есть сайт по умолчанию. Но так нельзя делать запросы в принципе, это не соответствует стандарту. Нужно всегда указывать хост, иначе ответ не гарантирован. Сегодня он один, а завтра другой. Некоторые библиотеки вообще могут так не работать. Виртуальные хосты являются неотъемлемым атрибутом HTTP 1.1. Их нельзя игнорировать.
Сейчас мы можем сделать GET-запрос с использованием протокола версии 1.1 и посмотреть, что он нам вернет:
telnet google.com 80
GET / HTTP/1.1
host: google.com
HTTP/1.1 301 Moved Permanently
Location: http://www.google.com/
Content-Type: text/html; charset=UTF-8
Date: Fri, 28 Feb 2020 06:06:40 GMT
Expires: Sun, 29 Mar 2020 06:06:40 GMT
Cache-Control: public, max-age=2592000
Server: gws
Content-Length: 219
X-XSS-Protection: 0
X-Frame-Options: SAMEORIGIN
<HTML><HEAD><meta http-equiv="content-type" content="text/html;charset=utf-8">
<TITLE>301 Moved</TITLE></HEAD><BODY>
<H1>301 Moved</H1>
The document has moved
<A HREF="http://www.google.com/">here</A>.
</BODY></HTML>
Как мы уже знаем, есть много разных кодов ответа. В итоге мы получили ответ, код которого отличается от 200. Здесь есть еще одна интересная деталь, которая введена в HTTP 1.1. После выполнения запроса мы не выпали из telnet и не оказались в bash. Это значит, что подключение не было закрыто, и мы можем продолжить вводить данные. Cделаем HEAD-запрос на тот же самый домен:
HEAD / HTTP/1.1
host: google.com
HTTP/1.1 301 Moved Permanently
Location: http://www.google.com/
Content-Type: text/html; charset=UTF-8
Date: Fri, 28 Feb 2020 06:11:31 GMT
Expires: Sun, 29 Mar 2020 06:11:31 GMT
Cache-Control: public, max-age=2592000
Server: gws
Content-Length: 219
X-XSS-Protection: 0
X-Frame-Options: SAMEORIGIN
Мы снова получили ответ, но уже без body, поскольку использовали HEAD, а не GET-запрос:
HTTP 1.1 вводит еще одно понятие по умолчанию, которое называется keep-alive. keep-alive означает, что соединение TCP, по которому ходит HTTP, не закрывается. Причем по умолчанию так должны себя вести все веб-сервера. Основная цель введения этой фичи в том, чтобы сократить использование ресурсов, уменьшить нагрузку на процессор, открывать меньше TCP-соединений (установка каждого TCP-соединения занимает время), уменьшить время ожидания (latency). Когда мы открываем сайт, то обычно с одного домена грузится несколько ресурсов. keep-alive позволяет открывать и использовать одно соединение, которое не будет закрыто до тех пор, пока это не будет указано явно, либо не произойдет таймаут. Таймаут зависит от того, какой браузер и какой веб-сервер используется.
Мы также можем указать, что хотим закрыть соединение. Для этого после установки соединения и передачи стандартных заголовков нужно передать еще один заголовок. Он называется connection: close
. Тогда keep-alive будет отключен, и после получения ответа мы увидим сообщение, что хост закрыл соединение: Connection closed by foreign host.
Дополнительные материалы

Остались вопросы? Задайте их в разделе «Обсуждение»
Вам ответят команда поддержки Хекслета или другие студенты
- Статья «Как учиться и справляться с негативными мыслями»
- Статья «Ловушки обучения»
- Статья «Сложные простые задачи по программированию»
- Урок «Как эффективно учиться на Хекслете»
- Вебинар «Как самостоятельно учиться»
Для полного доступа к курсу нужен базовый план
Базовый план откроет полный доступ ко всем курсам, упражнениям и урокам Хекслета, проектам и пожизненный доступ к теории пройденных уроков. Подписку можно отменить в любой момент.