Чтобы быть членом общества, человеку нужно соблюдать правила. Компьютеру тоже нужно соблюдать правила, чтобы быть участником сети. Эти правила называются сетевыми протоколами. В современных компьютерных сетях, объединённых Всемирной паутиной, насчитывается более семи тысяч протоколов. Но одним из самых важных для работы интернета без преувеличения можно назвать протокол HTTP (HyperText Transfer Protocol, протокол передачи гипертекста).
HTTP входит в состав сетевой модели TCP/IP как протокол верхнего, прикладного уровня. Модели и протоколы подробно рассмотрены в статье «Сетевые протоколы: что это и для чего используются», а вопросы безопасности — в статье «В чем разница протоколов HTTP и HTTPS». Теперь же давайте сосредоточимся на обмене данными между клиентским устройством и сервером.
Сбор данных
Вместо разбора сухой теории предлагаем рассмотреть взаимодействие веб-браузера и интернет-сервера с практической стороны. Для этого давайте воспользуемся «Инструментами разработчика», входящими в состав всех современных браузеров. Открыть панель инструментов можно с помощью клавиши F12, сочетания Сtrl + Shift + I или пункта меню настройки в разделе «Дополнительные инструменты». Сейчас нас интересует вкладка «Сеть»:
Другим вариантом получить передаваемые по сети данные может стать стать анализатор трафика (сниффер), например Wireshark. Для примера давайте выполним запрос к ресурсу www.ru по незащищённому протоколу HTTP:
А вот заголовок ответа на этот запрос:
Обратите внимание, поскольку НTTP-запрос отправляется поверх протокола TCP (Transmission Control Protocol, протокол управления передачей), который работает поверх IP (Internet Protocol, межсетевой протокол), который, в свою очередь, использует технологию пакетной передачи Ethernet, каждый из этих уровней добавляет к передаваемым данным свой набор служебной информации:
Так выглядит структура кадра (frame), передаваемого по сети. Если внимательно посмотреть на правую колонку окна Wireshark, то перед данными запроса и ответа можно увидеть набор дополнительных символов. Выбрав нужный пункт в левой колонке, можно получить детальную информацию по каждому заголовку.
Важно, что сетевой трафик, передаваемый по защищённому протоколу HTTPS, зашифрован, поэтому при попытке прослушать такие соединения мы увидим лишь нечитаемый набор символов.
Но сейчас нас интересует только структура прикладного уровня, поэтому давайте остановимся на полученных данных.
Структура протокола HTTP
HTTP-запрос (HTTP Request), как показывает нам Wireshark, в необработанном виде может выглядеть примерно так:
GET /index.html HTTP/1.1
Host: www.ru
Connection: keep-alive
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36 Edg/119.0.0.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Accept-Encoding: gzip, deflate
Accept-Language: ru,en;q=0.9,en-GB;q=0.8,en-US;q=0.7
Этот запрос состоит из двух частей — стартовой строки (Starting line) и заголовков (Headers), но может также содержать необязательную часть — тело сообщения (Message Body), отделённое от заголовков одной или несколькими пустыми строками:
Стартовая строка определяет тип запроса и имеет вид:
Наш HTTP-запрос выполняется методом GET, URI (Uniform Resource Identifier, унифицированный идентификатор ресурса) указывает на документ index.html в корневом разделе ресурса, а поле «версия» HTTP содержит значение 1.1.
Методы HTTP-запросов
HTTP-методы могут быть такими:
- OPTIONS. Запрашивает возможности сервера или поддерживаемые им методы.
- GET. Используется для запроса содержимого по указанному URI. Может содержать дополнительные параметры после знака вопроса (Query String), например /path/to/page?param1=value1,param2=value2
- HEAD. То же, что GET, но запрашивает только заголовки. Обычно используется для проверки указанного адреса или, например, для получения размера документа перед его загрузкой.
- POST. Применяется для передачи данных на сервер, таких как заполненные веб-формы или загружаемые файлы.
- PUT. Используется для загрузки содержимого запроса по указанному URI. Отличается от POST тем, что, если загружаемые данные уже существуют на сервере, то этот метод обновит их, а не создаст новую копию.
- PATCH. То же, что PUT, но применяется к части данных.
- DELETE. Удаляет указанные данные с сервера.
- TRACE. Позволяет клиенту получить информацию, вносимую или изменяемую промежуточными серверами.
- CONNECT. Запускает TCP/IP туннель, то есть двустороннюю связь с сервером.
Подробнее о методах HTTP можно узнать, например, в Википедии или базе знаний Mozilla MDN.
Заголовки HTTP
После стартовой строки в HTTP-запросе передаются заголовки (HTTP Headers) — строки, содержащие пару ключ-значение, разделённую двоеточием. Ключ, или название заголовка, не чувствителен к регистру, но по историческим причинам обычно каждое слово в составе ключа пишется с заглавной буквы.
Заголовки HTTP-запросов можно разделить на основные (General Headers), заголовки запроса (Request Headers) и сущности (Entity Headers). Основные и заголовки сущности применяются и к запросам клиента, и к ответам сервера, а заголовки запроса, как следует из названия, — только к запросам. Заголовки сущности необязательны и могут передаваться в том случае, если у запроса есть какое-либо тело (body), например при использовании метода POST.
Клиент также может включать в HTTP-запрос собственные заголовки, названия которых обычно начинаются с префикса X.
Вот список самых распространённых заголовков, включаемых в HTTP-запросы:
- Host. Содержит имя домена или IP-адрес, к которому выполняется запрос. Также может включать необязательный номер порта, отделённый от адреса двоеточием.
- Connection. Позволяет удерживать соединение открытым после завершения запроса (keep-alive) для экономии сетевых ресурсов.
- Accept. Указывает, какие типы содержимого (Multipurpose Internet Mail Extensions, MIME) может понять клиент.
- Accept-Encoding. Обычно определяет алгоритм сжатия контента.
- Accept-Language. Указывает предпочитаемый язык клиента.
- Cache-Control. Инструкции по кешированию запросов и ответов.
- Refer. Предоставляет исходный адрес, с которого пользователь перешёл на текущую страницу.
- Cookie. Содержит сохранённые на стороне клиента фрагменты данных, обычно используемые для сохранения состояния соединения. Cookie могут устанавливаться как сервером, так и клиентом.
- Authorization. Используется для проверки подлинности пользователя. Токен авторизации, передаваемый в этом поле, не требует хранения данных на стороне сервера. Этот метод является альтернативой аутентификации с помощью cookie и имеет как преимущества, так и недостатки. Может быть полезен в сетевых сервисах или распределённых системах.
- User-Agent. Характеристики клиента, по которым сервер может определить производителя и версию браузера, тип приложения и операционную систему пользователя.
С полным списком заголовков можно ознакомиться, например, в Википедии или MDN.
Ответ сервера
Теперь, когда мы разобрались с отправкой запросов, давайте подробно рассмотрим ответы сервера (HTTP Response).
Увидеть заголовки ответов сервера в необработанном виде можно, например, с помощью команды curl
:
curl -I http://www.ru
HTTP/1.1 200 OK
Date: Mon, 11 Dec 2023 08:19:17 GMT
Content-Type: text/html; charset=utf-8
Content-Length: 16654
Connection: keep-alive
X-Powered-By: Express
ETag: W/"410e-+oLejaw6dLcN1MX4POjPnPw26dk"
X-RID: a24782178c58a93f21dd3f9cf718affe
Как видите, структура ответов немного отличается от структуры запросов. Во-первых, стартовая строка имеет другой формат:
В нашем случае исследуемый сервер работает по протоколу HTTP/1.1, а на GET-запрос вернул код состояния 200 с пояснением OK.
Во-вторых, вместо заголовков запроса, разумеется, используются заголовки ответа (Response Headers).
Чаще всего в HTTP-ответах используются такие заголовки:
- Сontent-type. Указывает MIME-тип отправленного контента.
- Сontent-language. Описывает язык содержимого.
- Server. Описывает программное обеспечение сервера, отправившего ответ.
- Set-Cookie. В этом поле клиенту отправляются данные cookie, который он должен сохранить локально. При следующем запросе клиент отправит cookie обратно на сервер. Конечно, клиент может изменить эти данные перед отправкой, если это разрешено политикой безопасности.
После заголовков сервер передаёт тело ответа, которое в нашем случае представляет собой документ в формате HTML (HyperText Markup Language, язык гипертекстовой разметки):
Процесс отрисовки страницы в браузере, в свою очередь, порождает запросы дополнительной информации. Это могут быть могут быть CSS-стили, JS-скрипты, изображения, видео, JSON, XML и другие данные. В нашем примере список всех запрошенных ресурсов расположен в левой колонке. Кликнув на каждый пункт, можно увидеть заголовки и тело ответа.
Коды состояний
Код состояния HTTP-ответа показывает, завершился запрос успехом или нет. Коды ответов можно разделить на пять групп:
- информационные коды, 100...199;
- успешные коды, 200...299;
- коды перенаправления, 300...399;
- коды клиентских ошибок, 400...499;
- коды серверных ошибок, 500...599.
Вот список некоторых кодов состояния, чаще всего встречающихся в HTTP-ответах:
Информационные
- 100 Continue (Продолжить). Промежуточный ответ, который говорит о том, что запрос успешно принят.
- 102 Processing (В обработке). Указывает, что обработка запроса ещё не завершена.
Успешные
- 200 OK (Успешно). Пояснение говорит само за себя. Запрос успешно выполнен в соответствии с переданным методом.
- 201 Created (Создано). В результате выполнения запроса PUT был создан ресурс.
- 206 Partial Content (Частичное содержимое). Используется для загрузки контента в несколько потоков.
Сообщения о перенаправлениях
- 301 Moved Permanently (Перемещён на постоянной основе). Означает, что URL запрашиваемого ресурса был изменён.
- 302 Found (Найдено). Указывает, что запрошенный ресурс временно изменён. Например, после успешной авторизации клиент может быть перенаправлен на страницу своего профиля.
- 304 Not Modified (Не модифицировано). Используется для кеширования. Если запрошенный ресурс не был изменён, клиент может продолжать использовать сохранённую версию ответа.
Клиентские
- 400 Bad Request (Недействительный запрос). Означает, что сервер не может корректно обработать полученные данные.
- 401 Unauthorized (Неавторизованно). Для получения ответа на этот запрос нужна авторизация.
- 403 Forbidden (Запрещено). У клиента нет прав доступа к запрашиваемой странице. В отличие от 401, дальнейшая аутентификация невозможна.
- 404 Not Found (Не найдено). Сервер не смог найти запрашиваемую страницу. Пожалуй, это самый известный в интернете код ответа.
- 405 Method Not Allowed (Метод не разрешён). Вызов этого метода запрещён на стороне сервера. Обязательные методы GET и HEAD не могут быть запрещены.
Серверные
- 500 Internal Server Error (Внутренняя ошибка). В процессе обработки запроса сервер столкнулся с ошибкой, которую не смог обработать.
- 501 Not Implemented (Не реализовано). Сервер не поддерживает запрашиваемый метод. Методы GET и HEAD являются обязательными и не должны возвращать этот код.
- 502 Bad Gateway (Плохой шлюз). Эта ошибка обычно означает, что в процессе обработки запроса сервер выполнил обращение к внутренней службе, но получил недействительный ответ.
- 503 Service Unavailable (Сервис недоступен). Зачастую причиной этой ошибки бывает отключение или перегрузка сервера.
- 504 Gateway Timeout (тайм-аут шлюза). Этот ответ об ошибке возвращается, когда сервер не может получить ответ от внутренней службы вовремя.
Полный список кодов состояния можно найти здесь.
Серверные и клиентские ошибки должны быть представлены пользователю с необходимыми пояснениями. Пример обработки ошибок на стороне сервера приведён в статье «Установка и настройка nginx: пошаговая инструкция».
Разбор параметров ответа
Теперь давайте рассмотрим ответ сервера с практической точки зрения. Для примера выполним запрос к ресурсу https://firstvds.ru с помощью уже знакомой нам команды curl
.
Заметьте, поскольку curl выступает в роли клиента, данные будут дешифрованы и мы можем запросить информацию по защищённому протоколу HTTPS:
curl -I https://firstvds.ru
HTTP/2 200
server: ddos-guard
strict-transport-security: max-age=31536000
content-security-policy: upgrade-insecure-requests;
content-security-policy: default-src 'self' ; style-src https: 'unsafe-inline'; script-src 'self' 'unsafe-eval'
https://www.google-analytics.com/ https://metrika.yandex.ru/ https://www.youtube.com/;
set-cookie: __ddg1_=some_uniq_value; Domain=.firstvds.ru; HttpOnly; Path=/; Expires=Fri, 06-Dec-2024 08:45:30 GMT
content-type: text/html; charset=UTF-8
vary: Accept-Encoding
cache-control: must-revalidate, no-cache, no-store, private
date: Thu, 07 Dec 2023 08:38:05 GMT
x-drupal-dynamic-cache: MISS
content-language: ru
x-content-type-options: nosniff
x-frame-options: SAMEORIGIN
expires: Sun, 19 Nov 1978 05:00:00 GMT
x-generator: Drupal 10 (https://www.drupal.org)
server-timing: requestTime;dur=1701938730.305354
x-drupal-cache: HIT
set-cookie: _c_fid=another_uniq_value; expires=Sun, 04 Dec 2033 08:45:30 GMT; Max-Age=315360000; path=/; domain=.firstvds.ru; secure; samesite=none
x-xss-protection: 1; mode=block
referrer-policy: no-referrer-when-downgrade
content-security-policy: default-src 'self' ; ...
strict-transport-security: max-age=31536000
Тело ответа можно получить, указав параметр -v
:
Прежде, чем рассмотреть параметры ответа, давайте отметим, что согласно данным, указанным в стартовой строке, исследуемый сервер использует протокол HTTP второй версии. Здесь стоит, хотя бы кратко, перечислить ключевые преимущества HTTP/2 перед HTTP/1.1:
- Скорость. За счёт отсутствия блокировок соединения и использования бинарного формата передачи данных HTTP/2 быстрее загружает страницы в браузер, быстрее устанавливает соединение, быстрее обменивается данными между браузером и сервером.
- Безопасность. Протокол HTTP/2 для сжатия заголовков использует алгоритм HPACK, который не позволяет злоумышленникам получать авторизационные cookie из сжатых данных. Кроме того, просмотр передаваемой информации с помощью сниффера теряет смысл, так как данные отправляются в двоичном виде.
Также важно отметить, что протокол HTTP/2 позволяет объединить (мультиплексировать) несколько потоков данных в одно соединение. Кроме того, во второй версии задействованы такие механизмы, как отправка данных по инициативе сервера (Server Push), контроль потоков (Flow Control) и обработка ошибок, что не только повышает производительность, но и делает соединение более устойчивым.
Если вы владелец сервера и ещё не используете современный протокол HTTP/2, рекомендуем рассмотреть возможность его включения, это совсем не сложно.
Надеемся, мы вас убедили и теперь можем вернуться к разбору заголовков из нашего примера:
- Server: ddos-guard. Говорит о том, что ресурс использует защиту от DDoS-атак (Distributed Denial of Service, распределенный отказ в обслуживании) — разновидности хакерских атак с целью вызвать перегрузку сервера. Наличие такой защиты обеспечивает бесперебойную работу сайта, что хорошо и для посетителей, и для владельцев интернет-ресурса.
- Set-Cookie. Так как спецификация HTTP не предусматривает сохранение состояния между запросами, приложение должно позаботиться об этом самостоятельно. Например, если ресурс предоставляет пользователю доступ к личному кабинету, то при каждом запросе сервер должен проверять, авторизован ли посетитель, и если да, то кто он. Cookie — один из вариантов идентификации клиента.
Если ваш ресурс использует cookie, рекомендуем уменьшать объём передаваемой в этом поле информации насколько возможно. Дело в том, что, например, при использовании мобильных сетей клиент может находиться в плохих условиях связи. Но мощность сигнала сотовой вышки гораздо выше мощности, излучаемой антенной мобильного устройства, в этом случае передача большого объёма данных от клиента к серверу может значительно снизить скорость загрузки сайта. Поэтому все данные лучше хранить на стороне сервера, а в поле cookie передавать только их идентификатор.
Также при передаче данных cookie важно следовать требованиям безопасности. Например, включить параметры Secure и HttpOnly.
- Content-Type: сообщает о том, что в теле ответа передаётся текст в формате HTML в универсальной кодировке UTF-8.
- Content-Language: указывает браузеру на предпочитаемый язык страницы — русский.
- Expires: ограничивает дату валидности ответа. Используется по соображениям безопасности.
- User-Agent: характеристики клиентского устройства. Curl по умолчанию не передаёт данные клиента, но при запросе из браузера в примерах выше мы видим тип операционной системы (Linux) и версию веб-браузера (Microsoft Edge 119).
- Content-Security-Policy: содержит настройки политик безопасности для внешних ресурсов, обеспечивающих анализ статистики посещений сайта, таких как Google Analytics и Яндекс Метрика. Не влияет на посетителей, но позволяет собирать и анализировать массу необходимой для ведения бизнеса информации — количество посещений ресурса, географические параметры, поведенческие факторы, конверсию и так далее. Такие статистические данные используются на подавляющем большинстве современных коммерческих интернет-ресурсов.
- X-Generator: информирует нас, что сервер использует систему управления контентом Drupal. Если вы находитесь на этапе выбора платформы для построения вашего сайта, рекомендуем рассмотреть все альтернативные варианты до принятия архитектурных решений, не забывая проверять скорость загрузки страниц для каждого из них. Методика оценки параметров быстродействия рассмотрена в статье «Как провести нагрузочное тестирование».
В современном мире знание основ работы интернета давно стало необходимостью, особенно если вы занимаетесь электронной коммерцией, оказываете онлайн-услуги или просто ведёте блог.
Очень надеемся, что нам удалось дать вам действительно полезные советы по самым важным аспектам обмена данными во Всемирной паутине, которые в дальнейшем вы сможете применить на практике.