HTTP 1.1

Протокол HTTP 1.1 расширяет возможности предыдущей версии и добавляет виртуальные хосты. Сейчас мы посмотрим, для чего это нужно, и как это работает.

Предыдущая версия требует только одного заголовка (request line). В ней мы описываем, какой путь на сайте мы хотим посмотреть (query string). Но упоминания сайта как такового здесь нет. При этом мы подключаемся по 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.


Дополнительные материалы

  1. Стандарт HTTP 1.1
  2. Википедия / Постоянное HTTP-соединение

Для полного доступа к курсу, нужна профессиональная подписка

Профессиональная подписка откроет полный доступ ко всем курсам Хекслета, даст возможность обращаться за помощью к менторам и пожизненный доступ к теории пройденных уроков. Подписку можно отменить в любой момент.

Получить доступ
115
курсов
892
упражнения
2241
час теории
3196
тестов

Зарегистрироваться

или войти в аккаунт

Курсы программирования для новичков и опытных разработчиков. Начните обучение бесплатно.

  • 115 курсов, 2000+ часов теории
  • 800 практических заданий в браузере
  • 250 000 студентов

Нажимая кнопку «Зарегистрироваться», вы даёте своё согласие на обработку персональных данных в соответствии с «Политикой конфиденциальности» и соглашаетесь с «Условиями оказания услуг».

Наши выпускники работают в компаниях:

Логотип компании Альфа Банк
Логотип компании Rambler
Логотип компании Bookmate
Логотип компании Botmother

Есть вопрос или хотите участвовать в обсуждении?

Зарегистрируйтесь или войдите в свой аккаунт

Нажимая кнопку «Зарегистрироваться», вы даёте своё согласие на обработку персональных данных в соответствии с «Политикой конфиденциальности» и соглашаетесь с «Условиями оказания услуг».