HTTP – текстовый протокол, с помощью которого взаимодействуют клиент, например, браузер и сервер. Работает это так. Пользователь шлет определенный запрос на сервер, запрашивая или передавая нужные данные, а сервер, в зависимости от запроса, выполняет нужную логику и возвращает результат, обычно это HTML-страница либо редирект.
Для того чтобы посмотреть, как работает HTTP, мы будем использовать сервис HTTP Server, созданный специально для экспериментов. Он включает в себя ненастоящие данные, с которыми можно попрактиковаться. Для запросов используется специальная утилита, которая называется telnet (пример HTTP-запроса, выполненного с помощью утилиты telnet).
# Передаем адрес сайта и указываем tcp порт
# После этого происходит подключение к серверу по протоколу tcp
telnet http.hexlet.app 80
HTTP — это протокол прикладного уровня, предназначенный для общения между клиентом и сервером на разных компьютерах. Однако сам по себе HTTP не может соединять удаленные компьютеры; для этого используются другие протоколы, такие как TCP. TCP создает канал для общения между программами на удаленных компьютерах, для чего необходимы IP-адрес целевого компьютера и порт, на котором работает нужная программа.
Команда telnet выше делает именно это, она выполняет соединение по TCP и только после этого входит в режим взаимодействия по HTTP. При условии, что указан правильный ip-адрес и порт для соединения. И на этом моменте возникает два вопроса:
Мы передали адрес сайта, откуда берется ip-адрес? Любой адрес сайта это просто имя, за которым скрывается ip-адрес. Имя задано для удобства, так его проще запомнить. Однако все сетевые программы, среди которых браузеры и telnet, выполняют преобразование имени сайта в его ip-адрес. Делается это с помощью системы DNS, еще одного столпа интернета.
# Пример того, как можно узнать ip-адрес с помощью утилиты ping
# В вашем случае адрес может быть другим, ip-адреса могут меняться
# Опция -с устанавливает количество отправляемых пакетов
ping -c 4 http.hexlet.app # 188.114.97.0
# Затем можно использовать его для соединения с сервером
telnet 188.114.97.0 80
Почему порт имеет номер 80? Это общепринятое соглашение. Сайты, доступные по HTTP, доступны на порту 80, а по HTTPS – на порту 443. Именно поэтому в браузерах порты не указываются, браузер подставляет их автоматически.
Если соединение произошло успешно, то telnet выводит на экран такие строчки:
telnet http.hexlet.app 80
Trying 188.114.97.0...
Connected to http.hexlet.app.
Escape character is '^]'.
После подключения веб-сервер входит в режим ожидания HTTP-запроса. Осталось его послать.
Что из себя представляет сам запрос?
Запрос состоит из нескольких частей. Первая часть — стартовая строка (request line). Вторая — заголовки.
В стартовой строке мы указываем специальное слово, еще говорят "глагол". В HTTP описаны разные глаголы, но мы сейчас не будем вдаваться в подробности. Просто скажем, что они определяют, как реагировать на этот запрос. И в данном случае мы будем использовать глагол HEAD. Он очень простой, и просит сервер отдать только заголовки, без содержимого. Более распространенным является GET. Именно с помощью GET мы запрашиваем содержимое сайта.
После глагола указывается путь к ресурсу request URI. Если мы указываем /
, это обозначает просто корень сайта. Ресурс может быть любым, например, /users
— может быть ресурсом пользователей, а /courses
— ресурсом курсов. Имя ресурса зависит не только от того, к какому ресурсу мы хотим получить доступ, но и от сервера. Разные серверы предоставляют доступ к разным ресурсам.
Дальше все, что нужно сделать, это указать название протокола и его версию. В этом курсе рассматриваются версии HTTP 1.0 и 1.1, это основа протокола и знакомство с ним стоит начинать именно с них. Между версиями есть принципиальные отличия, которые нужно хорошо знать и понимать. Версия 1.0 продолжает использоваться в различных целях утилитами командной строки.
В принципе этого достаточно, и для 1.0 больше ничего делать не нужно:
HEAD /http-protocol/example HTTP/1.0
Дальше идут заголовки. Что это? Заголовки позволяют передавать дополнительную информацию, например браузеры предоставляют информацию о себе, чтобы было понятно откуда идет запрос. Кроме этого они указывают какие форматы сжатия поддерживают, в каком формате готовы принимать ответ и так далее. Количество стандартных заголовков достаточно большое, помимо них можно добавлять любые свои.
Давайте рассмотрим, как выглядят заголовки. Мы указываем имя и через двоеточие какое-то значение: REFERER: value. Заголовки часто указывают заглавными буквами, но регистр здесь не важен. Порядок заголовков также не специфицирован. В каком бы порядке мы ни передали заголовки, тело ответа будет разбираться только все вместе.
Браузерами используется много заголовков, например, user-agent. Этот заголовок используется для аналитики, а также, когда необходимо адаптировать страницы сайта под разные экраны или браузеры. Но и без него все должно работать:
HEAD /http-protocol/example HTTP/1.0
User-Agent: google сhrome
Важно помнить, поскольку это протокол, и у него есть определенные правила, то нарушать их нельзя. HTTP — текстовый протокол. Все правила основаны на простых соглашениях. Например, несколько заголовков отделяются друг от друга переводом строки (и никак иначе!). Мы не можем записать их в одну строку, через запятую или как-то еще. Все очень строго. А каким образом сервер поймет, что вы закончили передавать данные? Это должен быть какой-то маркер, определитель. В HTTP это делается с помощью двух переводов строки. После этого сервер считает что все данные были отправлены и больше данных не будет. То есть фактически два перевода строки (перевод после последнего заголовка и пустая строка) приводят к отправке данных.
Что из себя представляет ответ?
Давайте сделаем запрос и посмотрим, что нам вернется в ответ. Сделаем HEAD запрос и посмотрим, что будет возвращено:
telnet http.hexlet.app 80
Trying 188.114.97.0...
Connected to http.hexlet.app.
Escape character is '^]'.
HEAD /http-protocol/example HTTP/1.0
host: http.hexlet.app
HTTP/1.1 200 OK
Date: Sat, 18 Jan 2020 09:24:50 GMT
Expires: -1
Cache-Control: private, max-age=0
Content-Type: text/html; charset=ISO-8859-1
P3P: CP="This is not a P3P policy! See g.co/p3phelp for more info."
Server: gws
X-XSS-Protection: 0
X-Frame-Options: SAMEORIGIN
Set-Cookie: 1P_JAR=2020-01-18-09; expires=Mon, 17-Feb-2020 09:24:50 GMT; path=/; domain=.google.com; Secure
Set-Cookie: NID=196=wsHLMAMfnAaSyF7zduokI8TJeE5UoIKPHYC58HYH93VMnev9Nc2bAjhRdzoc4UhmuOd7ZVCorDnzGDe51yPefsRMeVyOFnYdHYYgQNqI8A1dYuk4pDK4OJurQgL4lX8kiNGSNi_kkUESFQ-MqLCB_YspxA9JRejhZdkTRtGyHNk; expires=Sun, 19-Jul-2020 09:24:50 GMT; path=/; domain=.google.com; HttpOnly
Accept-Ranges: none
Vary: Accept-Encoding
Connection closed by foreign host.
В ответ на запрос приходит response, который состоит из status line, например, HTTP/1.1 200 OK
. Эта строка указывает на используемый протокол (в данном случае HTTP/1.1
, о котором мы поговорим в следующем уроке) и статус ответа 200 OK
. В HTTP определено множество статусов, таких как 400 и 500, которые информируют о различных ситуациях, например, о том, что информация не найдена или произошла ошибка на сервере. Каждый статус имеет мнемоническое название, передаваемое в последней части строки. Статус 200 OK
означает, что запрос выполнен успешно — success!
Далее выводится большое количество различных заголовков. В них нет ничего сложного, и их не нужно все учить (есть какие-то общие, и они достаточно понятны). Все заголовки состоят из ключа, двоеточия и значения. Можно заметить, что есть вещи, связанные с кодировкой, кешированием. Некоторые заголовки специфичны для текущего сервера. Например, X-XSS-Protection: 0
, где X
указывает на кастомный заголовок. Но никакой веб-сервер, никакой веб-браузер не будут ломаться при посылке таких дополнительных заголовков.
Именно в HTTP 1.0 в конце после получения данных происходит закрытие соединения.
В конце мы видим одну интересную деталь: Connection closed by foreign host. Запрос соединения был закрыт внешним хостом. Так работает практически все в интернете. Обычно серверы настроены на 30-секундный интервал и закрывают соединение, если в течение этого интервала ничего не приходит.
Поэтому с telnet новичкам работать чуть тяжелее. Они медленно набирают запрос, и за это время соединение закрывается, что довольно неприятно. Поэтому лучше делать записи в отдельном файле и после этого вставлять их в telnet.
Дополнительные материалы

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