Рассматриваем основы работы HTTP, применяем HTTP на практике в терминале, используем Wireshark для анализа пакетов HTTP.
Основы HTTP
HTTP расшифровывается как Hypertext Transfer Protocol, протокол передачи гипертекста. Сейчас это один из самых популярных протоколов интернет, основа Web.
HTTP находится на прикладном уровне в моделях OSI и TCP/IP.
Концепцию Web предложил в 1989 году Тим Бернерс-Ли из Европейского центра ядерных исследований (ЦЕРН). Основные компоненты Web по предложению Тима Бернерс-Ли:
Язык гипертекстовой разметки страниц HTML.
Протокол передачи гипертекстовых страниц HTTP.
Web-сервер.
Текстовый web-браузер.
Сейчас Web устроен более сложно, браузеры поддерживают не только текст, но и изображения, видео, могут запускать код на JavaScript и многое другое.
Протокол HTTP используется браузером для того, чтобы загрузить с Web-сервера HTML страницы и другие ресурсы, которые нужны для показа страниц. Также HTTP сейчас активно применяется в API.
Uniform Resource Locator
Важную роль в работе HTTP играет Uniform Resource Locator, сокращенно URL – единообразный определитель местонахождения ресурса. Именно URL используется для того, чтобы указать, к какой странице мы хотим получить доступ.
URL состоит из трех основных частей:
Название протокола, в примере на рисунке протокол HTTP.
Адрес сервера, на котором размещен ресурс. Можно использовать IP-адрес или доменное имя. Адрес сервера отделяется от названия протокола двоеточием и двумя слешами.
Адрес ресурса на сервере. Это может быть HTML-страница, изображение, видео или ресурс другого типа. В примере на рисунке адрес страницы: /courses/networks.
В URL не обязательно использовать только протокол HTTP, вот примеры с другими протоколами:
https://ya.ru
ftp://example.com
Также URL не обязательно должен указывать на страницы в HTML, можно использовать ресурсы в разных форматах, например:
URL может включать достаточно большое количество других компонентов, кроме протокола, адреса сервера и адреса ресурса. Более подробно почитать о них можно в документе RFC 1738, Uniform Resource Locators (URL).
Версии протокола HTTP
В ЦЕРН в 1991 году разработали экспериментальную версию протокола HTTP 0.9. Первая открытая версияHTTP 1.0появилась в 1996 году, она описана в документе RFC 1945.
Почти сразу после HTTP 1.0, в 1997 году, вышла обновленная версия протокола HTTP 1.1. В этой версии добавили кэширование, постоянное соединение, аутентификацию и некоторые другие возможности. Документы RFC, описывающие HTTP 1.1, несколько раз обновлялись, сейчас действует RFC 9112 от 2022 года. Версия HTTP 1.1 используется сейчас.
В 2015 году вышла версия HTTP/2(описана в RFC 9113), основная задача которой – повышение производительности. Самая последняя версия HTTP/3, описанная в RFC 9114, использует на транспортном уровне протокол QUIC вместо TCP.
Версии HTTP/1.1, HTTP/2 и HTTP/3 отличаются форматом передачи данных по сети, но логика работы у них одинаковая. Эта логика описана в документе RFC 9110 HTTP Semantics.
HTTP передает данные по сети в открытом виде, что не очень хорошо с точки зрения безопасности. Шифрование данных используется в протоколе HyperText Transfer Protocol Secure, сокращенно HTTPS.
В этой статье (и соответствующих видео) мы рассмотрим версию HTTP/1.1 и логику работы HTTP в целом. Далее будут отдельные статьи по HTTP/2, HTTP/3 и HTTPS.
Протокол HTTP
Протокол HTTP работает в режиме запрос-ответ. Клиент, например, браузер, передает на сервер запрос к определенному ресурсу, например, Web-странице. Сервер в ответ отправляет клиенту этот ресурс или сообщение об ошибке, если ресурс передать нельзя.
HTTP/1.1 использует текстовый режим работы, то есть от клиента к серверу и обратно передаются обычные строки. Это просто и удобно для людей, которые могут понять, что именно передается без использования дополнительных инструментов. Однако для компьютеров это не самый удобный формат, т.к. приходится заниматься парсингом строк. Поэтому HTTP/2 и HTTP/3 используют бинарный режим работы.
На транспортном уровне HTTP использует протокол TCP (кроме HTTP/3, в котором применяется QUIC), порт Web-сервера по-умолчанию: 80.
Запрос HTTP
Запрос HTTP состоит из трех основных частей:
Запрос
Заголовки (не обязательно)
Тело сообщения (не обязательно)
Пример простого запроса HTTP в текстовом режиме:
GET /courses/networks HTTP/1.1
Host: asozykin.ru
В первой строке указывается сам запрос, который также состоит из трех частей:
Метод HTTP GET указывает, какое действие требуется выполнить с ресурсом. В примере метод GET говорит о том, что мы хотим получить (загрузить) ресурс.
Адрес ресурса /courses/networks – путь к странице на Web-сервере, которую мы хотим загрузить.
Версия протокола HTTP/1.1.
Во второй строке указывается заголовок Host. Этот заголовок является обязательным в версии HTTP/1.1, в нем задается доменное имя сервера, к которому направлен запрос. Сейчас активно используется виртуальный хостинг: один Web-сервер на одном IP-адресе может обслуживать несколько сайтов с разными доменными именами. Чтобы понять, какому именно сайту предназначен запрос, нужно указать доменное имя сайта в заголовке Host.
В HTTP используется следующий формат заголовка: Название заголовка: значение заголовка
В примере название заголовка Host, значение – asozykin.ru (доменное имя сайта, к которому направлен запрос).
Если заголовков в запросе несколько, то каждый указывается в отдельной строке.
Методы HTTP
Метод HTTP говорит о том, какое действие с ресурсом мы хотим совершить. В примере запроса мы видели метод GET, который предназначен для получения ресурса. Кроме GET в HTTP есть и другие методы, наиболее важные из которых определены в документе RFC 9110 HTTP Semantics.
Название метода
Описание метода
GET
Запрос на передачу ресурса.
HEAD
Запрос на передачу ресурса, но сам ресурс в ответе не передается, только заголовки.
POST
Передача данных на сервер для обработки указанного ресурса.
PUT
Размещение ресурса на сервере (если такой ресурс уже есть на сервере, то он замещается).
DELETE
Удаление ресурса на сервере.
CONNECT
Установка соединение с сервером на основе ресурса.
OPTIONS
Запрос поддерживаемых методов HTTP для ресурса и других параметров коммуникации.
TRACE
Запрос на трассировку сообщения: сервер должен включить в свой ответ исходный запрос, на который он отвечает. Это полезно, когда запрос проходит через промежуточные устройства, которые могут изменить запрос, например, добавить заголовки.
Полный список всех существующих методов HTTP находится в документе Hypertext Transfer Protocol (HTTP) Method Registry, который сопровождается организацией Internet Assigned Numbers Authority (IANA). IANA поддерживает не только этот документ, но и большое количество других документов с возможными значениями различных параметров сетевых протоколов. Далее в статье мы встретимся еще с двумя полезными документами от IANA.
Следует отметить, что методы HTTP и соответствующие им действия – это соглашения, которые желательно, но не обязательно соблюдать. Вполне возможно, что некоторая реализация Web-сервера в ответ на запрос GET будет удалять запрошенный ресурс. Однако большая часть реализаций соблюдает соглашения.
На практике в Web чаще всего используются два метода: GET для запроса Web-страниц и POST для передачи данных из браузера на сервер, например, после заполнения формы.
Ответ HTTP
Ответ HTTP, как и запрос, состоит из трех частей:
Статус ответа
Заголовки (не обязательно)
Тело сообщения (не обязательно)
Пример ответа на запрос выше:
HTTP/1.1 200 ОК
Content-Type: text/html; charset=UTF-8
Content-Length: 5161
Текст Web-страницы…
В HTTP/1.1 ответ, также как и запрос, представляет собой обычные текстовые строки.
Первая строка ответа состоит из двух частей:
Версия протокола, в примере HTTP/1.1. Версию указывать не обязательно.
Код статуса ответа, в примере 200 ОК, запрос обработан успешно.
Ответ содержит два заголовка, которые следуют после строки с кодом статуса:
Content-Type, тип содержимого, которое передается в теле сообщения. Значение "text/html; charset=UTF-8" означает, что в теле сообщения страница HTML в кодировке UTF-8.
Content-Length, размер содержимого, в байтах. В примере размер страницы в теле сообщения 5161 байт.
После заголовков в теле ответа находится запрошенная Web-страница (в примере она не показана для сокращения объема). Тело сообщения отделено от заголовков пустой строкой.
Коды статусов ответов HTTP
Первая строка ответа HTTP содержит код статуса ответа – число в диапазоне от 100 до 599, которое характеризует результат выполнения запроса. Возможные коды статусов ответов описаны в документе RFC 9110 HTTP Semantics.
Коды статусов ответов разделены на пять классов, которые определяются по первой цифре кода:
2ХХ (успешное выполнение): запрос был успешно принят и понят.
3ХХ (перенаправление): для выполнения запроса необходимо предпринять дополнительные действия.
4ХХ (ошибка клиента): запрос содержит синтаксическую ошибку или не может быть выполнен.
5ХХ (ошибка сервера): запрос от клиента оформлен правильно, но при его обработке произошла ошибка на стороне сервера.
Часто встречающиеся коды статусов ответов приведены в таблице.
Код статуса ответа
Описание
1ХХ (информация)
101 Switching Protocols
Запрос принят, сервер предлагает дальнейшее взаимодействие выполнять по другому протоколу (например, WebSocket). Желаемый протокол должен быть указан в заголовке Upgrade ответа.
2ХХ (успешное выполнение)
200 OK
Запрос выполнен успешно.
201 Created
В результате выполнения запроса на сервере был успешно создан ресурс (например, в ответ на запрос PUT).
3ХХ (перенаправление)
301 Moved Permanently
Запрошенный ресурс был перемещен. Новый URL ресурса указывается в заголовке ответа Location. В дальнейшем клиенту рекомендуется использовать новый URL.
302 Found
Запрошенный ресурс был временно перемещен в другое место. Новый URL ресурса указывается в заголовке ответа Location. В дальнейшем клиенту рекомендуется использовать старый URL, т.к. перемещение временное.
304 Not Modified
Запрошенный ресурс не был изменен, поэтому можно взять ресурс из кэша, а не передавать его по сети.
4ХХ (ошибка клиента)
400 Bad Request
Запрос не может быть обработан из-за ошибки синтаксиса.
403 Forbidden
Доступ к запрошенному клиентом ресурсу запрещен.
404 Not Found
Запрошенный ресурс не найден на сервере.
5ХХ (ошибка сервера)
500 Internal Server Error
Запрос не может быть выполнен из-за внутренней ошибки в программном обеспечении сервера.
501 Not Implemented
Сервер не поддерживает запрошенную функциональность, например, не может выполнить запрошенный метод HTTP для указанного ресурса.
505 HTTP Version Not Supported
Версия HTTP, указанная в запросе, не поддерживается.
Если вам удобнее изучать новые материалы по видео, то вот видеолекция по основам работы протокола HTTP.
Практика в терминале
HTTP/1.1 работает в текстовом режиме, поэтому запросы к Web-серверу можно передавать просто подключившись терминалом по TCP на 80 порт (порт Web-сервера по умолчанию). Ответы Web-сервер также будет отправлять в терминал в виде текста.
Однако сейчас почти все сайты используют защищенный протокол HTTPS, который шифрует данные при передаче по сети. Такие данные не получится посмотреть терминалом.
Специально для курса я создал сайт networkscourse.ru, который доступен по протоколу HTTP без шифрования. На сайте достаточно простые страницы, которые удобно смотреть в терминале или Wireshark. Далее в примерах будем использовать этот сайт.
Подключение к Web-серверу
В Linux или macOS подключиться к Web-серверу можно в командной строке с помощью команды telnet:
Connection type: Other, Raw (передача «сырых» данных (Raw), без шифрования, как в SSH, или вставки управляющих символов, как в telnet).
Передача запроса HTTP
После подключения к Web-серверу вы увидите пустой экран. Сервер ожидает запрос HTTP. Для начала давайте запросим корневую страницу сервера. Для этого в терминале нужно написать:
GET / HTTP/1.1
Host: networkscourse.ru
В первой строке пишем запрос: метод HTTP GET, адрес страницы / (корневая страница Web-сервера), версия HTTP/1.1
Для версии HTTP/1.1 обязателен заголовок Host, указываем его во второй строке.
Чтобы сообщить серверу об окончании запроса после заголовка вводим пустую строку (нажимаем Enter).
Ответ HTTP
Web-сервер получает запрос, ищет нужную Web-страницу и отправляет в терминал следующий ответ:
HTTP/1.1 200 OK
Connection: keep-alive
Content-Length: 237
Server: GitHub.com
Content-Type: text/html; charset=utf-8
Last-Modified: Sat, 15 Oct 2022 17:47:01 GMT
Access-Control-Allow-Origin: *
ETag: "634af215-ed"
expires: Fri, 10 May 2024 09:01:39 GMT
Cache-Control: max-age=600
x-proxy-cache: MISS
X-GitHub-Request-Id: C848:3634AF:B56066:BA3EF8:663DE01A
Accept-Ranges: bytes
Age: 0
Date: Fri, 10 May 2024 14:38:52 GMT
Via: 1.1 varnish
X-Served-By: cache-fra-eddf8230031-FRA
X-Cache: HIT
X-Cache-Hits: 0
X-Timer: S1715351932.404979,VS0,VE100
Vary: Accept-Encoding
X-Fastly-Request-ID: 1c209b352a70e784c4ea6031a847634890f1fd6b
<h1>Онлайн курс "Компьютерные сети"</h1>
Сайт для практических занятий по курсу <a href='https://www.asozykin.ru/courses/networks_online'>Компьютерные сети</a>.
В терминале запрос и начало ответа выглядят следующим образом:
Первая строка ответа содержит статус 200 ОК, запрос выполнен успешно.
После статуса указываются заголовки. Сервер включил в ответ достаточно большое количество заголовков, наиболее важные из них:
Connection: keep-alive – не разрывать соединение TCP после получения ответа. Это полезно с точки зрения производительности, почему именно рассмотрим далее в курсе после изучения деталей работы протокола TCP.
Content-Length: 237 – длина ответа 237 байт, корневая страница сайта достаточно простая.
Server: GitHub.com – ответ прислал сервер GitHub.com, я использую бесплатный хостингGitHub Pages.
Content-Type: text/html; charset=utf-8 – тело сообщения содержит HTML страницу в кодировке UTF-8.
Last-Modified: Sat, 15 Oct 2022 17:47:01 GMT – дата последнего изменения страницы.
Date: Fri, 10 May 2024 14:38:52 GMT – дата отправки ответа.
Заголовки ETag, expires и Cache-Control используются для управления кэшированием в HTTP. По кэшированию в HTTP в курсе есть отдельное видео.
Последняя часть ответа – это запрошенная HTML страница. Она отделена от заголовков пустой строкой. Давайте еще раз приведу эту страницу отдельно от статуса ответа и заголовков:
<h1>Онлайн курс "Компьютерные сети"</h1>
Сайт для практических занятий по курсу <a href='https://www.asozykin.ru/courses/networks_online'>Компьютерные сети</a>.
Попробуйте открыть в браузере ссылку http://networkscourse.ru, просмотреть код страницы и сравнить с тем, который содержится в ответе Web-сервера в терминале.
Видео с практикой HTTP в текстовом режиме
Более подробно о запуске запросов HTTP в текстовом режиме в терминале можно посмотреть в видео.
В видео в дополнение к корневой странице запрашиваются еще два ресурса:
Ранее мы отправляли запрос HTTP самостоятельно из терминала, в этот раз с помощью Wireshark рассмотрим, как выглядят запросы, которые отправляет браузер. Для этого запустим Wireshark и в браузере откроем сайт http://networkscourse.ru (обратите внимание, что протокол в URL должен быть http, а не https, иначе данные будут зашифрованы).
В Wireshark устанавливаем фильтр "http" (в левом верхнем углу окна), после этого будут показаны только пакеты, которые используют протокол HTTP. Нас интересуют два пакета, обведенные красным прямоугольником: это запрос и ответ HTTP.
В верхнем окне Wireshark кратко показывает содержимое пакетов. Первый пакет – это запрос GET к корневой странице сайта по HTTP/1.1. Второй пакет – ответ HTTP со статусом 200 OK, в теле ответа содержится страница в HTML.
Запрос HTTP
Если мы откроем первый пакет с запросом HTTP, то увидим следующую подробную информацию.
Запрос состоит из одной строки, которую Wireshark показывал также в окне со списком пакетов:
GET / HTTP/1.1
В терминале к запросу мы добавляли только один заголовок Host, а браузер кроме этого добавил еще 8 заголовков. Наиболее важные заголовки из тех, которые мы не рассматривали ранее:
User-Agent, агент пользователя – тип программы клиента, который отправляет запрос.
Accept –список форматов ресурсов, которые понимает браузер. Полный список допустимых форматов содержится в документе IANA «Media Types».
Accept-Encoding – список допустимых форматов представления, которые понимает браузер.Чаще всего указываются поддерживаемые браузером алгоритмы сжатия данных, в примере gzip и deflate. Полный список возможных представлений содержится в документе IANA «HTTP Parameters».
Accept-Language – список предпочитаемых языков в порядке убывания их приоритета. Мой браузер запрашивает страницу на русском, если ее нет, то на английском.
Ответ HTTP
Ответ HTTP от Web-сервера в Wireshark выглядит так же, как и в терминале.
Первая строка содержит статус кода ответа 200 OK, после нее идут заголовки, которые мы уже разбирали.
После заголовков Wireshark показывает Web-страницу из ответа сервера.
Повторный запрос страницы
Давайте посмотрим, что произойдет, если в браузере повторно открыть страницу http://networkscourse.ru. Интересующие нас пакеты в Wireshark выделены красным прямоугольником.
Давайте начнем рассмотрение с ответа.
Код статуса ответа 304 Not Modified. Это означает, что клиент уже ранее запрашивал такую страницу, и страница на сервере не изменилась с момента последнего запроса от клиента. Обычно браузеры сохраняют копии загруженных по HTTP ресурсов в кэш на локальном компьютере. Если страница на сервере не изменилась, то браузеру для ускорения показа страницы можно взять ее из кэша, а не ждать загрузки по сети.
В ответ от сервера со статусом 304 Not Modified запрошенный ресурс не включается, поэтому такое сообщение передается по сети достаточно быстро.
Как браузер и сервер понимают, что страница не изменилась? Для этого используются заголовки для управления кэшем в HTTP. При первой отправке страницы клиенту сервер включил заголовки Last-Modified и ETag.
В заголовке Last-Modified указывается дата последнего изменения страницы (я обновлял страницу достаточно давно, в 2022 году). Заголовок ETag содержит уникальный идентификатор, созданный на основе содержания страницы. Как правило, это какой-либо хэш. В примере уникальный идентификатор переданной страницы "634af215-ed".
Клиент при повторном запросе страницы, которая уже есть в кэше браузера, использует запрос Conditional GET, запрос GET с условием. В этом запросе клиент просит сервер передать страницу только если она была изменена. Определить, что страница была изменена можно по ETag (ETag страницы на сервере не совпадает с ETag страницы в кэше браузера) или по дате изменения. Клиент вставляет в запрос GET с условием известные ему значения ETag и даты изменения страницы в заголовки If-None-Match и If-Modified-Since.
Сервер, при получении запроса GET с условием, проверяет выполнение условий:
Сравнивает ETag в заголовке запроса If-None-Match с ETag запрошенной страницы на сервере.
Сравнивает дату изменения в заголовке запроса If-Modified-Since с датой изменения запрошенной страницы на сервере.
Если страница была изменена, то сервер передает ответ с кодом статуса 200 ОК и новой страницей. В противном случае отправляется ответ с кодом статуса 304 Not Modified, сама страница в ответ не включается.
Видео с практикой по HTTP в Wireshark
Более подробно посмотреть выполнение практики по разбору пакетов HTTP в Wireshark можно в видео.
Заключение
В статье рассмотрены основы работы протокола HTTP, Hypertext Transfer Protocol, протокола передачи гипертекста. В настоящее время это один из самых популярных протоколов в интернет, основа Web. HTTP также активно используется для реализации API.
HTTP работает в режиме запрос-ответ:
Запрос содержит метод HTTP (как правило, GET или POST), адрес ресурса, к которому происходит обращение, и заголовки HTTP. Также запрос может включать тело сообщения.
Ответ HTTP включает код статуса выполнения (например, 200 ОК), заголовки HTTP и запрошенный ресурс (например, Web-страницу).
HTTP/1.1 работает в текстовом режиме, поэтому его можно легко протестировать в терминале или Wireshark. Более современные версии HTTP/2 и HTTP/3 передают данные в бинарном виде и обеспечивают более высокую производительность по сравнению с HTTP/1.1. Но логика работы у всех протоколов одинаковая: используются одни и те же методы HTTP, коды статусов ответов, заголовки и т.п.
Версии HTTP/2 и HTTP/3, а также защищенный протокол HTTPS, будут подробно рассмотрены в следующих статьях (и соответствующих видео).