Ультимативный гайд по HTTP. Структура запроса и ответа

Ультимативный гайд по HTTP. Структура запроса и ответа Госуслуги

Время на прочтение

Вашему вниманию предлагается описание основных аспектов протокола HTTP — сетевого протокола, с начала 90-х и по сей день позволяющего вашему браузеру загружать веб-страницы. Данная статья написана для тех, кто только начинает работать с компьютерными сетями и заниматься разработкой сетевых приложений, и кому пока что сложно самостоятельно читать официальные спецификации.

HTTP — широко распространённый протокол передачи данных, изначально предназначенный для передачи гипертекстовых документов (то есть документов, которые могут содержать ссылки, позволяющие организовать переход к другим документам).

Аббревиатура HTTP расшифровывается как HyperText Transfer Protocol, «протокол передачи гипертекста». В соответствии со спецификацией OSI, HTTP является протоколом прикладного (верхнего, 7-го) уровня. Актуальная на данный момент версия протокола, HTTP 1.1, описана в спецификации RFC 2616.

Протокол HTTP предполагает использование клиент-серверной структуры передачи данных. Клиентское приложение формирует запрос и отправляет его на сервер, после чего серверное программное обеспечение обрабатывает данный запрос, формирует ответ и передаёт его обратно клиенту. После этого клиентское приложение может продолжить отправлять другие запросы, которые будут обработаны аналогичным образом.

Задача, которая традиционно решается с помощью протокола HTTP — обмен данными между пользовательским приложением, осуществляющим доступ к веб-ресурсам (обычно это веб-браузер) и веб-сервером. На данный момент именно благодаря протоколу HTTP обеспечивается работа Всемирной паутины.

Также HTTP часто используется как протокол передачи информации для других протоколов прикладного уровня, таких как SOAP, XML-RPC и WebDAV. В таком случае говорят, что протокол HTTP используется как «транспорт».

API многих программных продуктов также подразумевает использование HTTP для передачи данных — сами данные при этом могут иметь любой формат, например, XML или JSON.

Как правило, передача данных по протоколу HTTP осуществляется через TCP/IP-соединения. Серверное программное обеспечение при этом обычно использует TCP-порт 80 (и, если порт не указан явно, то обычно клиентское программное обеспечение по умолчанию использует именно 80-й порт для открываемых HTTP-соединений), хотя может использовать и любой другой.

Как отправить HTTP-запрос?

Самый простой способ разобраться с протоколом HTTP — это попробовать обратиться к какому-нибудь веб-ресурсу вручную. Представьте, что вы браузер, и у вас есть пользователь, который очень хочет прочитать статьи Анатолия Ализара.

Предположим, что он ввёл в адресной строке следующее:

Соответственно вам, как веб-браузеру, теперь необходимо подключиться к веб-серверу по адресу alizar.habrahabr.ru.

Для этого вы можете воспользоваться любой подходящей утилитой командной строки. Например, telnet:

После того, как вы подключитесь к серверу, нужно отправить HTTP-запрос. Это, кстати, очень легко — HTTP-запросы могут состоять всего из двух строчек.

Стартовая (начальная) строка запроса для HTTP 1.1 составляется по следующей схеме:

Метод URI HTTP/Версия

Метод (в англоязычной тематической литературе используется слово method, а также иногда слово verb — «глагол») представляет собой последовательность из любых символов, кроме управляющих и разделителей, и определяет операцию, которую нужно осуществить с указанным ресурсом. Спецификация HTTP 1.1 не ограничивает количество разных методов, которые могут быть использованы, однако в целях соответствия общим стандартам и сохранения совместимости с максимально широким спектром программного обеспечения как правило используются лишь некоторые, наиболее стандартные методы, смысл которых однозначно раскрыт в спецификации протокола.

URI (Uniform Resource Identifier, унифицированный идентификатор ресурса) — путь до конкретного ресурса (например, документа), над которым необходимо осуществить операцию (например, в случае использования метода GET подразумевается получение ресурса). Некоторые запросы могут не относиться к какому-либо ресурсу, в этом случае вместо URI в стартовую строку может быть добавлена звёздочка (астериск, символ «*»). Например, это может быть запрос, который относится к самому веб-серверу, а не какому-либо конкретному ресурсу. В этом случае стартовая строка может выглядеть так:

Версия определяет, в соответствии с какой версией стандарта HTTP составлен запрос. Указывается как два числа, разделённых точкой (например 1.1).

Для того, чтобы обратиться к веб-странице по определённому адресу (в данном случае путь к ресурсу — это «/»), нам следует отправить следующий запрос:

GET / HTTP/1.1
Host: alizar.habrahabr.ru

При этом учитывайте, что для переноса строки следует использовать символ возврата каретки (Carriage Return), за которым следует символ перевода строки (Line Feed). После объявления последнего заголовка последовательность символов для переноса строки добавляется дважды.

Впрочем, в спецификации HTTP рекомендуется программировать HTTP-сервер таким образом, чтобы при обработке запросов в качестве межстрочного разделителя воспринимался символ LF, а предшествующий символ CR, при наличии такового, игнорировался. Соответственно, на практике бо́льшая часть серверов корректно обработает и такой запрос, где заголовки отделены символом LF, и он же дважды добавлен после объявления последнего заголовка.

Если вы хотите отправить запрос в точном соответствии со спецификацией, можете воспользоваться управляющими последовательностями
и
:

Как прочитать ответ?

Стартовая строка ответа имеет следующую структуру:

HTTP/Версия Код состояния Пояснение

Версия протокола здесь задаётся так же, как в запросе.

Код состояния (Status Code) — три цифры (первая из которых указывает на класс состояния), которые определяют результат совершения запроса. Например, в случае, если был использован метод GET, и сервер предоставляет ресурс с указанным идентификатором, то такое состояние задаётся с помощью кода 200. Если сервер сообщает о том, что такого ресурса не существует — 404. Если сервер сообщает о том, что не может предоставить доступ к данному ресурсу по причине отсутствия необходимых привилегий у клиента, то используется код 403. Спецификация HTTP 1.1 определяет 40 различных кодов HTTP, а также допускается расширение протокола и использование дополнительных кодов состояний.

Пояснение к коду состояния (Reason Phrase) — текстовое (но не включающее символы CR и LF) пояснение к коду ответа, предназначено для упрощения чтения ответа человеком. Пояснение может не учитываться клиентским программным обеспечением, а также может отличаться от стандартного в некоторых реализациях серверного ПО.

После стартовой строки следуют заголовки, а также тело ответа. Например:

HTTP/1.1 200 OK
Server: nginx/1.2.1
Date: Sat, 08 Mar 2014 22:53:46 GMT
Content-Type: application/octet-stream
Content-Length: 7
Last-Modified: Sat, 08 Mar 2014 22:53:30 GMT
Connection: keep-alive
Accept-Ranges: bytes

Wisdom

Тело ответа следует через два переноса строки после последнего заголовка. Для определения окончания тела ответа используется значение заголовка Content-Length (в данном случае ответ содержит 7 восьмеричных байтов: слово «Wisdom» и символ переноса строки).

Но вот по тому запросу, который мы составили ранее, веб-сервер вернёт ответ не с кодом 200, а с кодом 302. Таким образом он сообщает клиенту о том, что обращаться к данному ресурсу на данный момент нужно по другому адресу.

В ответ на этот запрос веб-сервер Хабрахабра уже выдаст ответ с кодом 200 и достаточно большой документ в формате HTML.

Если вы уже успели вжиться в роль, то можете теперь прочитать полученный от сервера HTML-код, взять карандаш и блокнот, и нарисовать профайл Ализара — в принципе, именно этим бы на вашем месте браузер сейчас и занялся.

А что с безопасностью?

Сам по себе протокол HTTP не предполагает использование шифрования для передачи информации. Тем не менее, для HTTP есть распространённое расширение, которое реализует упаковку передаваемых данных в криптографический протокол SSL или TLS.

Название этого расширения — HTTPS (HyperText Transfer Protocol Secure). Для HTTPS-соединений обычно используется TCP-порт 443. HTTPS широко используется для защиты информации от перехвата, а также, как правило, обеспечивает защиту от атак вида man-in-the-middle — в том случае, если сертификат проверяется на клиенте, и при этом приватный ключ сертификата не был скомпрометирован, пользователь не подтверждал использование неподписанного сертификата, и на компьютере пользователя не были внедрены сертификаты центра сертификации злоумышленника.

На данный момент HTTPS поддерживается всеми популярными веб-браузерами.

А есть дополнительные возможности?

Протокол HTTP предполагает достаточно большое количество возможностей для расширения. В частности, спецификация HTTP 1.1 предполагает возможность использования заголовка Upgrade для переключения на обмен данными по другому протоколу. Запрос с таким заголовком отправляется клиентом. Если серверу требуется произвести переход на обмен данными по другому протоколу, то он может вернуть клиенту ответ со статусом «426 Upgrade Required», и в этом случае клиент может отправить новый запрос, уже с заголовком Upgrade.

Такая возможность используется, в частности, для организации обмена данными по протоколу WebSocket (протокол, описанный в спецификации RFC 6455, позволяющий обеим сторонам передавать данные в нужный момент, без отправки дополнительных HTTP-запросов): стандартное «рукопожатие» (handshake) сводится к отправке HTTP-запроса с заголовком Upgrade, имеющим значение «websocket», на который сервер возвращает ответ с состоянием «101 Switching Protocols», и далее любая сторона может начать передавать данные уже по протоколу WebSocket.

Что-то ещё, кстати, используют?

На данный момент существуют и другие протоколы, предназначенные для передачи веб-содержимого. В частности, протокол SPDY (произносится как английское слово speedy, не является аббревиатурой) является модификацией протокола HTTP, цель которой — уменьшить задержки при загрузке веб-страниц, а также обеспечить дополнительную безопасность.

Увеличение скорости обеспечивается посредством сжатия, приоритизации и мультиплексирования дополнительных ресурсов, необходимых для веб-страницы, чтобы все данные можно было передать в рамках одного соединения.

Опубликованный в ноябре 2012 года черновик спецификации протокола HTTP 2.0 (следующая версия протокола HTTP после версии 1.1, окончательная спецификация для которой была опубликована в 1999) базируется на спецификации протокола SPDY.

Многие архитектурные решения, используемые в протоколе SPDY, а также в других предложенных реализациях, которые рабочая группа httpbis рассматривала в ходе подготовки черновика спецификации HTTP 2.0, уже ранее были получены в ходе разработки протокола HTTP-NG, однако работы над протоколом HTTP-NG были прекращены в 1998.

На данный момент поддержка протокола SPDY есть в браузерах Firefox, Chromium/Chrome, Opera, Internet Exporer и Amazon Silk.

И что, всё?

В общем-то, да. Можно было бы описать конкретные методы и заголовки, но фактически эти знания нужны скорее в том случае, если вы пишете что-то конкретное (например, веб-сервер или какое-то клиентское программное обеспечение, которое связывается с серверами через HTTP), и для базового понимания принципа работы протокола не требуются. К тому же, всё это вы можете очень легко найти через Google — эта информация есть и в спецификациях, и в Википедии, и много где ещё.

Впрочем, если вы знаете английский и хотите углубиться в изучение не только самого HTTP, но и используемых для передачи пакетов TCP/IP, то рекомендую прочитать вот эту статью.

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

Удачи и плодотворного обучения!

Привет! Меня зовут Ивасюта Алексей, я техлид команды Bricks в Авито в кластере Architecture. Я решил написать цикл статей об истории и развитии HTTP, рассмотреть каждую из его версий и проблемы, которые они решали и решают сейчас.

Весь современный веб построен на протоколе HTTP. Каждый сайт использует его для общения клиента с сервером. Между собой сервера тоже часто общаются по этому протоколу. На данный момент существует четыре его версии и все они до сих пор используются. Поэтому статьи будут полезны инженерам любых уровней и специализаций, и помогут систематизировать знания об этой важной технологии.

Ультимативный гайд по HTTP. Структура запроса и ответа

Что такое HTTP

HTTP — это гипертекстовый протокол передачи данных прикладного уровня в сетевой модели OSI. Его представил миру Тим Бернерс-Ли в марте 1991 года. Главная особенность HTTP — представление всех данных в нём в виде простого текста. Через HTTP разные узлы в сети общаются между собой. Модель клиент-серверного взаимодействия классическая: клиент посылает запрос серверу, сервер обрабатывает запрос и возвращает ответ клиенту. Полученный ответ клиент обрабатывает и решает: прекратить взаимодействие или продолжить отправлять запросы.

Ещё одна особенность: протокол не сохраняет состояние между запросами. Каждый запрос от клиента для сервера — отдельная транзакция. Когда поступают два соседних запроса, сервер не понимает, от одного и того же клиента они поступили, или от разных. Такой подход значительно упрощает построение архитектуры веб-серверов.

Как правило, передача данных по HTTP осуществляется через открытое TCP/IP-соединение1. Серверное программное обеспечение по умолчанию обычно использует TCP-порт 80 для работы веб-сервера, а порт 443 — для HTTPS-соединений.

HTTPS (HTTP Secure) — это надстройка над протоколом HTTP, которая поддерживает шифрование посредством криптографических протоколов SSL и TLS. Они шифруют отправляемые данные на клиенте и дешифруют их на сервере. Это защищает данные от чтения злоумышленниками, даже если им удастся их перехватить.

HTTP/0

В 1991 году была опубликована первая версия протокола с названием HTTP/0.9. Эта реализация была проста, как топор. От интернет-ресурса того времени требовалось только загружать запрашиваемую HTML-страницу и HTTP/0.9 справлялся с этой задачей. Обычный запрос к серверу выглядел так:

В протоколе был определен единственный метод GET и и указывался путь к ресурсу. Так пользователи получали страничку. После этого открытое соединение сразу закрывалось.

HTTP/1

Годы шли и интернет менялся. Стало понятно, что нужно не только получать странички от сервера, но и отправлять ему данные. В 1996 году вышла версия протокола 1.0.

  • В запросе теперь надо было указывать версию протокола. Так сервер мог понимать, как обрабатывать полученные данные.
  • В ответе от сервера появился статус завершения обработки запроса.
  • К запросу и ответу добавился новый блок с заголовками.
  • Добавили поддержку новых методов:

Структура запроса

Простой пример запроса:

GET /path HTTP/1.0
Content-Type: text/html; charset=utf-8
Content-Length: 4
X-Custom-Header: value

test

В первой строчке указаны метод запроса — GET, путь к ресурсу — /path и версия протокола —  HTTP/1.0.

Далее идёт блок заголовков. Заголовки — это пары ключ: значение, каждая из которых записывается с новой строки и разделяется двоеточием. Они передают дополнительные данные и настройки от клиента к серверу и обратно.

HTTP — это текстовый протокол, поэтому и все данные передаются в виде текста. Заголовки можно отделить друг от друга только переносом строки. Нельзя использовать запятые, точку с запятой, или другие разделители. Всё, что идет после имени заголовка с двоеточием и до переноса строки, будет считаться значением заголовка2.

В примере серверу передали три заголовка:

  • Content-Type — стандартный заголовок. Показывает, в каком формате будут передаваться данные в теле запроса или ответа.
  • Content-Length — сообщает длину контента в теле запроса в байтах.
  • X-Custom-Header — пользовательские заголовки, начинающиеся с X- с произвольными именем. Через них реализуется специфическая логика обработки для конкретного сервера. Если веб-сервер не поддерживает такие заголовки, то он проигнорирует их.

После блока заголовков идёт тело запроса, в котором передается текст test.

А так может выглядеть ответ от сервера:

HTTP/1.1 200 OK
Date: Thu, 29 Jul 2021 19:20:01 GMT
Content-Type: text/html; charset=utf-8
Content-Length: 2
Connection: close
Server: gunicorn/19.9.0
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true

OK

В первой строке — версия протокола и статус ответа, например, 200 ОК. Далее идут заголовки ответа. После блока заголовков — тело ответа, в котором записан текст OK.

Статусы ответов

Клиенту зачастую недостаточно просто отправить запрос на сервер. Во многих случаях надо дождаться ответа и понять, как сервер обработал запрос. Для этого были придуманы статусы ответов. Это трёхзначные числовые коды с небольшими текстовыми обозначениями. Их можно увидеть в терминале или браузере. Сами коды делятся на 5 классов:

  • Информационные ответы: коды 100–199
  • Успешные ответы: коды 200–299
  • Редиректы: коды 300–399
  • Клиентские ошибки: коды 400–499
  • Серверные ошибки: коды 500–599

Мы рассмотрим основные коды, которые чаще всего встречаются в реальных задачах. С остальными более подробно можно ознакомиться в реестре кодов состояния HTTP.

Информационные ответы

100 Continue — промежуточный ответ. Он указывает, что запрос успешно принят.  Клиент может продолжать присылать запросы или проигнорировать этот ответ, если запрос был завершён.

101 Switching Protocol присылается в ответ на запрос, в котором есть заголовок Upgrade. Это означает, что сервер переключился на протокол, который был указан в заголовке. Такая методика используется, например, для переключения на протокол Websocket.

102 Processing — запрос получен сервером, но его обработка ещё не завершена.

Успешные ответы

200 OK — запрос принят и корректно обработан веб-сервером.

201 Created — запрос корректно обработан и в результате был создан новый ресурс. Обычно он присылается в ответ на POST запрос.

Редиректы

301 Moved Permanently — запрашиваемый ресурс на постоянной основе переехал на новый адрес. Тогда новый путь к ресурсу указывается сервером в заголовке Location ответа.

Клиент может изменить метод последующего запроса с POST на GET.

302 Found — указывает, что целевой ресурс временно доступен по другому URl. Адрес перенаправления может быть изменен в любое время, а клиент должен продолжать использовать действующий URI для будущих запросов. Тогда временный путь к ресурсу указывается сервером в заголовке Location ответа.

307 Temporary Redirect — имеет то же значение, что и код 302, за исключением того, что клиент не может менять метод последующего запроса.

308 Permanent Redirect — имеет то же значение, что и код 301, за исключением того, что клиент не может менять метод последующего запроса.

Клиентские ошибки

400 Bad Request — запрос от клиента к веб-серверу составлен некорректно. Обычно это происходит, если клиент не передаёт необходимые заголовки или параметры.

401 Unauthorized — получение запрашиваемого ресурса доступно только аутентифицированным пользователям.

403 Forbidden — у клиента не хватает прав для получения запрашиваемого ресурса. Например, когда обычный пользователь сайта пытается получить доступ к панели администратора.

404 Not Found — сервер не смог найти запрашиваемый ресурс.

405 Method Not Allowed — сервер знает о существовании HTTP-метода, который был указан в запросе, но не поддерживает его. В таком случае сервер должен вернуть список поддерживаемых методов в заголовке Allow ответа.

Серверные ошибки

500 Internal Server Error — на сервере произошла непредвиденная ошибка.

501 Not Implemented — метод запроса не поддерживается сервером и не может быть обработан.

502 Bad Gateway — сервер, действуя как шлюз или прокси, получил недопустимый ответ от входящего сервера, к которому он обращался при попытке выполнить запрос.

503 Service Unavailable — сервер не готов обработать запрос (например, из-за технического обслуживания или перегрузки). Обратите внимание, что вместе с этим ответом должна быть отправлена ​​удобная страница с объяснением проблемы. Этот ответ следует использовать для временных условий, а HTTP-заголовок Retry-After по возможности должен содержать расчётное время до восстановления службы.

504 Gateway Timeout — этот ответ об ошибке выдается, когда сервер действует как шлюз и не может получить ответ за отведенное время.

505 HTTP Version Not Supported — версия HTTP, используемая в запросе, не поддерживается сервером.

В HTTP из всего диапазона кодов используется совсем немного. Те коды, которые не используются для задания определенной логики в спецификации, являются неназначенными и могут использоваться веб-серверами для определения своей специфической логики. Это значит, что вы можете, например, придать коду 513 значение «Произошла ошибка обработки видео», или любое другое. Неназначенные коды вы можете посмотреть в реестре кодов состояния HTTP.3

Тело запроса и ответа

Тело запроса опционально и всегда отделяется от заголовков пустой строкой. А как понять, где оно заканчивается? Всё кажется очевидным: где кончается строка, там и заканчивается тело. Однако, два символа переноса строки в HTTP означают конец запроса и отправляют его на сервер. Как быть, если мы хотим передать в теле текст, в котором есть несколько абзацев с разрывами в две строки?

POST /path HTTP/1.1
Host: localhost

Первая строка

Вторая строка после разрыва

По логике работы HTTP соединение отправится сразу после второй пустой строки и сервер получит в качестве данных только строку Первая строка. Описанную проблему решает специальный заголовок Content-Length. Он указывает на длину контента в байтах. Обычно клиенты (например, браузеры) автоматически считают длину передаваемых данных и добавляют к запросу заголовок с этим значением. Когда сервер получит запрос, он будет ожидать в качестве контента ровно столько байт, сколько указано в заголовке.

MIME (Multipurpose Internet Mail Extensions, многоцелевые расширения интернет-почты) — стандарт, который является частью протокола HTTP. Задача MIME — идентифицировать тип содержимого документа по его заголовку. К примеру, текстовый файл имеет тип text/plain, а HTML-файл — text/html.

Для передачи данных в формате обычного текста надо указать заголовок Content-Type: text/plain, а для JSON — Content-Type: application/json.

Можно ли передать тело с GET-запросом?

Популярный вопрос на некоторых собеседованиях: «Можно ли передать тело с GET-запросом?». Правильный ответ — да. Тело запроса не зависит от метода. В стандарте не описана возможность принимать тело запроса у GET-метода, но это и не запрещено. Технически вы можете отправить данные в теле, но скорее всего веб-сервер будет их игнорировать.

Представим, что на абстрактном сайте есть форма аутентификации пользователя, в которой есть всего два поля: email и пароль.

Запрос на отправку данных будет выглядеть так:

Тут есть небольшая особенность. Как понять, где заканчивается ключ и начинается его значение, если в пароле будет присутствовать знак «=» ?

В этом случае сервер не сможет понять, как разбить строку на параметры и их значения. На самом деле значения кодируются при помощи механизма url encoding.5 При использовании этого механизма знак «=» будет преобразован в код %3D .

Тогда наш запрос приобретёт такой вид:

Query string

Данные на сервер можно передавать через тело запроса и через так называемую строку запроса Query String. Это параметры формата ключ=значение, которые располагаются в пути к ресурсу:

GET /files?key=value&key2=value2 HTTP/1.0

При этом параметры можно передавать прямо от корня домена:

GET /?key=value&key2=value2 HTTP/1.0

Query String имеет такой же формат, как и тело запроса с MIME application/x-www-form-urlencoded, только первая пара значений отделяется от адреса вопросительным знаком.

Некоторые инженеры ошибочно полагают, что Query String являются параметрами GET-запроса и даже называют их GET-параметрами, но на самом деле это не так. Как и тело запроса, Query String не имеет привязки к HTTP-методам и может передаваться с любым типом запросов.

Обычно параметры Query String используются в GET-запросах, чтобы конкретизировать получаемый ресурс. Например, можно получить на сервере список файлов, имена которых будут начинаться с переданного значения.

GET-запросы по своей идеологии должны быть идемпотентными. Это значит, что множественный вызов метода с одними и теми же параметрами должен приводить к одному и тому же результату. Например, поисковые боты перемещаются по сайту только по ссылкам и делают только GET-запросы, потому что исходя из семантики они не смогут таким образом изменить данные на сайте и повлиять на его работу.

На этом я закончу говорить про версию протокола 1.0, структуру ответов и запросов. В следующей статье я расскажу, что такое Cookies, для чего нужен CORS и как это всё работает. А пока напоследок оставлю полезные ссылки, которые упомянул в тексте:

Следующая статья: Ультимативный гайд по HTTP. Cookies и CORS

От переводчика: перед вами краткий обзор протокола HTTP и его истории — от версии 0.9 к версии 2.

HTTP — протокол, пронизывающий веб. Знать его обязан каждый веб-разработчик. Понимание работы HTTP поможет вам делать более качественные веб-приложения.

В этой статье мы обсудим, что такое HTTP, и как он стал именно таким, каким мы видим его сегодня.

Что такое HTTP?

Итак, рассмотрим для начала, что же такое HTTP? HTTP — протокол прикладного уровня, реализованный поверх протокола TCP/IP. HTTP определяет, как взаимодействуют между собой клиент и сервер, как запрашивается и передаётся контент по интернету. Под протоколом прикладного уровня я понимаю, что это лишь абстракция, стандартизующая, как узлы сети (клиенты и серверы) взаимодействуют друг с другом. Сам HTTP зависит от протокола TCP/IP, позволяющего посылать и отправлять запросы между клиентом и сервером. По умолчанию используется 80 порт TCP, но могут использоваться и другие. HTTPS, например, использует 443 порт.

HTTP/0. 9 — первый стандарт (1991)

Первой задокументированной версией HTTP стал HTTP/0.9, выпущенный в 1991 году. Это был самый простой протокол на свете, c одним-единственным методом — GET. Если клиенту нужно было получить какую-либо страницу на сервере, он делал запрос:

А от сервера приходил примерно такой ответ:

(response body)
(connection closed)

Вот и всё. Сервер получает запрос, посылает HTML в ответ, и как только весь контент будет передан, закрывает соединение. В HTTP/0.9 нет никаких заголовков, единственный метод — GET, а ответ приходит в HTML.

Итак, HTTP/0.9 стал первым шагом во всей дальнейшей истории.

HTTP/1. 0 — 1996

В отличие от HTTP/0.9, спроектированного только для HTML-ответов, HTTP/1.0 справляется и с другими форматами: изображения, видео, текст и другие типы контента. В него добавлены новые методы (такие, как POST и HEAD). Изменился формат запросов/ответов. К запросам и ответам добавились HTTP-заголовки. Добавлены коды состояний, чтобы различать разные ответы сервера. Введена поддержка кодировок. Добавлены составные типы данных (multi-part types), авторизация, кэширование, различные кодировки контента и ещё многое другое.

Помимо запроса клиент посылал персональную информацию, требуемый тип ответа и т.д. В HTTP/0.9 клиент не послал бы такую информацию, поскольку заголовков попросту не существовало.

Пример ответа на подобный запрос:

HTTP/1.0 200 OK
Content-Type: text/plain
Content-Length: 137582
Expires: Thu, 05 Dec 1997 16:00:00 GMT
Last-Modified: Wed, 5 August 1996 15:55:28 GMT
Server: Apache 0.84

(response body)
(connection closed)

В начале ответа стоит HTTP/1.0 (HTTP и номер версии), затем код состояния — 200, затем — описание кода состояния.

В новой версии заголовки запросов и ответов были закодированы в ASCII (HTTP/0.9 весь был закодирован в ASCII), а вот тело ответа могло быть любого контентного типа — изображением, видео, HTML, обычным текстом и т. п. Теперь сервер мог послать любой тип контента клиенту, поэтому словосочетание «Hyper Text» в аббревиатуре HTTP стало искажением. HMTP, или Hypermedia Transfer Protocol, пожалуй, стало бы более уместным названием, но все к тому времени уже привыкли к HTTP.

Один из главных недостатков HTTP/1.0 — то, что вы не можете послать несколько запросов во время одного соединения. Если клиенту надо что-либо получить от сервера, ему нужно открыть новое TCP-соединение, и, как только запрос будет выполнен, это соединение закроется. Для каждого следующего запроса нужно создавать новое соединение.

Почему это плохо? Давайте предположим, что вы открываете страницу, содержащую 10 изображений, 5 файлов стилей и 5 JavaScript файлов. В общей сложности при запросе к этой странице вам нужно получить 20 ресурсов — а это значит, что серверу придётся создать 20 отдельных соединений. Такое число соединений значительно сказывается на производительности, поскольку каждое новое TCP-соединение требует «тройного рукопожатия», за которым следует медленный старт.

Тройное рукопожатие

«Тройное рукопожатие» — это обмен последовательностью пакетов между клиентом и сервером, позволяющий установить TCP-соединение для начала передачи данных.

  • SYN — Клиент генерирует случайное число, например, x, и отправляет его на сервер.
  • SYN ACK — Сервер подтверждает этот запрос, посылая обратно пакет ACK, состоящий из случайного числа, выбранного сервером (допустим, y), и числа x + 1, где x — число, пришедшее от клиента.
  • ACK — клиент увеличивает число y, полученное от сервера и посылает y + 1 на сервер.

Примечание переводчика: SYN — синхронизация номеров последовательности, (англ. Synchronize sequence numbers). ACK — поле «Номер подтверждения» задействовано (англ. Acknowledgement field is significant).

Ультимативный гайд по HTTP. Структура запроса и ответа

Только после завершения тройного рукопожатия начинается передача данных между клиентом и сервером. Стоит заметить, что клиент может посылать данные сразу же после отправки последнего ACK-пакета, однако сервер всё равно ожидает ACK-пакет, чтобы выполнить запрос.

Тем не менее, некоторые реализации HTTP/1.0 старались преодолеть эту проблему, добавив новый заголовок Connection: keep-alive, который говорил бы серверу «Эй, дружище, не закрывай это соединение, оно нам ещё пригодится». Однако эта возможность не была широко распространена, поэтому проблема оставалась актуальна.

Помимо того, что HTTP — протокол без установления соединения, в нём также не предусмотрена поддержка состояний. Иными словами, сервер не хранит информации о клиенте, поэтому каждому запросу приходится включать в себя всю необходимую серверу информацию, без учёта прошлых запросов. И это только подливает масла в огонь: помимо огромного числа соединений, которые открывает клиент, он также посылает повторяющиеся данные, излишне перегружая сеть.

HTTP/1. 1 – 1999

Прошло 3 года со времён HTTP/1.0, и в 1999 вышла новая версия протокола — HTTP/1.1, включающая множество улучшений:

  • Новые HTTP-методы — PUT, PATCH, HEAD, OPTIONS, DELETE.
  • Идентификация хостов. В HTTP/1.0 заголовок Host не был обязательным, а HTTP/1.1 сделал его таковым.
  • Постоянные соединения. Как говорилось выше, в HTTP/1.0 одно соединение обрабатывало лишь один запрос и после этого сразу закрывалось, что вызывало серьёзные проблемы с производительностью и проблемы с задержками. В HTTP/1.1 появились постоянные соединения, т.е. соединения, которые по умолчанию не закрывались, оставаясь открытыми для нескольких последовательных запросов. Чтобы закрыть соединение, нужно было при запросе добавить заголовок Connection: close. Клиенты обычно посылали этот заголовок в последнем запросе к серверу, чтобы безопасно закрыть соединение.
  • Потоковая передача данных, при которой клиент может в рамках соединения посылать множественные запросы к серверу, не ожидая ответов, а сервер посылает ответы в той же последовательности, в которой получены запросы. Но, вы можете спросить, как же клиент узнает, когда закончится один ответ и начнётся другой? Для разрешения этой задачи устанавливается заголовок Content-Length, с помощью которого клиент определяет, где заканчивается один ответ и можно ожидать следующий.

Замечу, что для того, чтобы ощутить пользу постоянных соединений или потоковой передачи данных, заголовок Content-Length должен быть доступен в ответе. Это позволит клиенту понять, когда завершится передача и можно будет отправить следующий запрос (в случае обычных последовательных запросов) или начинать ожидание следующего ответа (в случае потоковой передачи).
Но в таком подходе по-прежнему оставались проблемы. Что, если данные динамичны, и сервер не может перед отправкой узнать длину контента? Получается, в этом случае мы не можем пользоваться постоянными соединениями? Чтобы разрешить эту задачу, HTTP/1.1 ввёл сhunked encoding — механизм разбиения информации на небольшие части (chunks) и их передачу.

  • Chunked Transfers если контент строится динамически и сервер в начале передачи не может определить Content-Length, он начинает отсылать контент частями, друг за другом, и добавлять Content-Length к каждой передаваемой части. Когда все части отправлены, посылается пустой пакет с заголовком Content-Length, установленным в 0, сигнализируя клиенту, что передача завершена. Чтобы сказать клиенту, что передача будет вестись по частям, сервер добавляет заголовок Transfer-Encoding: chunked.
  • В отличие от базовой аутентификации в HTTP/1.0, в HTTP/1.1 добавились дайджест-аутентификация и прокси-аутентификация.
  • Кэширование.
  • Диапазоны байт (byte ranges).
  • Кодировки
  • Согласование содержимого (content negotiation).
  • Клиентские куки.
  • Улучшенная поддержка сжатия.

Особенности HTTP/1.1 — отдельная тема для разговора, и в этой статье я не буду задерживаться на ней надолго. Вы можете найти огромное количество материалов по этой теме. Рекомендую к прочтению Key differences between HTTP/1.0 and HTTP/1.1 и, для супергероев, ссылку на RFC.

SPDY — 2009

Google пошёл дальше и стал экспериментировать с альтернативными протоколами, поставив цель сделать веб быстрее и улучшить уровень безопасности за счёт уменьшения времени задержек веб-страниц. В 2009 году они представили протокол SPDY.

Казалось, что если мы будем продолжать увеличивать пропускную способность сети, увеличится её производительность. Однако выяснилось, что с определенного момента рост пропускной способности перестаёт влиять на производительность. С другой стороны, если оперировать величиной задержки, то есть уменьшать время отклика, прирост производительности будет постоянным. В этом и заключалась основная идея SPDY.

Следует пояснить, в чём разница: время задержки — величина, показывающая, сколько времени займёт передача данных от отправителя к получателю (в миллисекундах), а пропускная способность — количество данных, переданных в секунду (бит в секунду).

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

В 2015 в Google решили, что не должно быть двух конкурирующих стандартов, и объединили SPDY с HTTP, дав начало HTTP/2.

HTTP/2 — 2015

Думаю, вы уже убедились, что нам нужна новая версия HTTP-протокола. HTTP/2 разрабатывался для транспортировки контента с низким временем задержки. Главные отличия от HTTP/1.1:

  • бинарный вместо текстового
  • мультиплексирование — передача нескольких асинхронных HTTP-запросов по одному TCP-соединению
  • сжатие заголовков методом HPACK
  • Server Push — несколько ответов на один запрос
  • приоритизация запросов
  • безопасность

Ультимативный гайд по HTTP. Структура запроса и ответа

Бинарный протокол

HTTP/2 пытается решить проблему выросшей задержки, существовавшую в HTTP/1.x, переходом на бинарный формат. Бинарные сообщения быстрее разбираются автоматически, но, в отличие от HTTP/1.x, не удобны для чтения человеком. Основные составляющие HTTP/2 — фреймы (Frames) и потоки (Streams).

Фреймы и потоки.

Каждый запрос и ответ HTTP/2 получает уникальный идентификатор потока и разделяется на фреймы. Фреймы представляют собой просто бинарные части данных. Коллекция фреймов называется потоком (Stream). Каждый фрейм содержит идентификатор потока, показывающий, к какому потоку он принадлежит, а также каждый фрейм содержит общий заголовок. Также, помимо того, что идентификатор потока уникален, стоит упомянуть, что каждый клиентский запрос использует нечётные id, а ответ от сервера — чётные.

Помимо HEADERS и DATA, стоит упомянуть ещё и RST_STREAM — специальный тип фреймов, использующийся для прерывания потоков. Клиент может послать этот фрейм серверу, сигнализируя, что данный поток ему больше не нужен. В HTTP/1.1 единственным способом заставить сервер перестать посылать ответы было закрытие соединения, что увеличивало время задержки, ведь нужно было открыть новое соединение для любых дальнейших запросов. А в HTTP/2 клиент может отправить RST_STREAM и перестать получать определённый поток. При этом соединение останется открытым, что позволяет работать остальным потокам.

Мультиплексирование

Это было частью отдельного RFC, специально нацеленного на оптимизацию отправляемых заголовков. В основе лежало то, что если мы постоянного обращаемся к серверу из одного и того же клиента, то в заголовках раз за разом посылается огромное количество повторяющихся данных. А иногда к этому добавляются ещё и куки, раздувающие размер заголовков, что снижает пропускную способность сети и увеличивает время задержки. Чтобы решить эту проблему, в HTTP/2 появилось сжатие заголовков.

Ультимативный гайд по HTTP. Структура запроса и ответа

Раз уж зашла речь о заголовках, позвольте добавить, что они не отличаются от HTTP/1.1, за исключением того, что добавилось несколько псевдозаголовков, таких как :method, :scheme, :host, :path и прочие.

Server Push

Server push — ещё одна потрясающая особенность HTTP/2. Сервер, зная, что клиент собирается запросить определённый ресурс, может отправить его, не дожидаясь запроса. Вот, например, когда это будет полезно: браузер загружает веб-страницу, он разбирает её и находит, какой ещё контент необходимо загрузить с сервера, а затем отправляет соответствующие запросы.

Server push позволяет серверу снизить количество дополнительных запросов. Если он знает, что клиент собирается запросить данные, он сразу их посылает. Сервер отправляет специальный фрейм PUSH_PROMISE, говоря клиенту: «Эй, дружище, сейчас я тебе отправлю вот этот ресурс. И не надо лишний раз беспокоить.» Фрейм PUSH_PROMISE связан с потоком, который вызвал отправку push-а, и содержит идентификатор потока, по которому сервер отправит нужный ресурс.

Приоритизация запросов

Клиент может назначить приоритет потоку, добавив информацию о приоритете во фрейм HEADERS, которым открывается поток. В любое другое время клиент может отправить фрейм PRIORITY, меняющий приоритет потока.

Если никакой информации о приоритете не указанно, сервер обрабатывает запрос асинхронно, т.е. без какого-либо порядка. Если приоритет назначен, то, на основе информации о приоритетах, сервер принимает решение, сколько ресурсов выделяется для обработки того или иного потока.

Насчёт того, должна ли безопасность (передача поверх протокола TLS) быть обязательной для HTTP/2 или нет, развилась обширная дискуссия. В конце концов было решено не делать это обязательным. Однако большинство производителей браузеров заявило, что они будут поддерживать HTTP/2 только тогда, когда он будет использоваться поверх TLS. Таким образом, хотя спецификация не требует шифрования для HTTP/2, оно всё равно станет обязательным по умолчанию. При этом HTTP/2, реализованный поверх TLS, накладывает некоторые ограничения: необходим TLS версии 1.2 или выше, есть ограничения на минимальный размер ключей, требуются эфемерные ключи и так далее.

Заключение

HTTP/2 может многое предложить для увеличения производительности, и, похоже, самое время начать его использовать.

Оригинал: Journey to HTTP/2, автор Kamran Ahmed.

Перевод: Андрей Алексеев, редактура: Анатолий Тутов, Jabher, Игорь Пелехань, Наталья Ёркина, Тимофей Маринин, Чайка Чурсина, Яна Крикливая.

В статье рассказывается:

  • Что такое HTTP
  • 3 составляющих системы HTTP
  • Структура сообщения и методы HTTP
  • Порядок работы HTTP протокола
  • Плюсы и минусы HTTP
  • Пройди тест и узнай, какая сфера тебе подходит: айти, дизайн или маркетинг.Бесплатно от Geekbrains

HTTP – это протокол для передачи информации, который появился на заре Интернета. Спустя десятилетия, он не потерял актуальности, но уже не является безальтернативным вариантом. По сути, данный протокол отвечает за то, получит ли конечный пользователь информацию по своему запросу или нет.

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

HTTP представляет собой протокол передачи данных. В древнегреческом языке слово протокол состоит из двух частей, которые можно перевести как «первый» и «клей». Раньше так называли листок, который приклеивался к свитку. Автор записывал на нем свое имя, дату написания и прочую служебную информацию. При этом для обывателя, который читал свиток, была важна его содержательная часть, а не информация о самом писателе.

Ультимативный гайд по HTTP. Структура запроса и ответа

Нечто похожее мы можем наблюдать и в HTTP протоколе. Обычному человеку вряд ли будет интересен принцип работы страниц сайтов, так как браузер сделает всю работу за него.

Итак, протокол — это совокупность правил, регламентирующих какое-либо мероприятие. В свою очередь, протокол передачи данных — это стандарт, предписывающий правила функциональных блоков в процессе передачи данных.

Теперь поговорим об аббревиатуре HTTP. HyperText Transfer Protocol можно перевести как «протокол передачи гипертекста».

Рассмотрим три определения данного термина, которые раскрывают его с разных сторон.

HTTP протокол — это протокол передачи данных седьмого уровня модели OSI, функционирующий на базе технологии клиент-сервер.

HTTP протокол — это абстракция над третьим и четвертым уровнем эталонной модели, которая расширяет возможности коммуникации между пользователями. На сегодняшний день благодаря этому своду предписаний можно передавать любые данные.

HTTP протокол – это своего рода правила дорожного движения в Сети. При этом в реальности люди нередко нарушают ПДД и не испытывают никаких неудобств, тогда как нарушение правил HTTP приводит к невозможности работы в Интернете.

3 составляющих системы HTTP

Участником обмена может являться любой инструмент или устройство, которое выступает в качестве представителя пользователя. Как правило, речь идет о веб-браузерах. При этом участником может являться программа, с которой работает инженер или веб-разработчик для устранения ошибок в своих приложениях.

Ультимативный гайд по HTTP. Структура запроса и ответа

3 составляющих системы HTTP

В отличие от браузера, сервер обычно не формирует запросы. Но с развитием Интернета появились технологии, которые позволили делать и это.

Для отображения веб-страницы браузер осуществляет отправку начального запроса и получает HTML-документ целевой страницы. Затем программа исследует полученный файл и запрашивает остальные данные, которые нужны для отображения содержания страницы.

Речь идет о исполняемых скриптах, информации о макете страницы (CSS таблицы стилей) и дополнительных ресурсов (изображений и видеофайлов, которые сами по себе не являются составляющими исходного документа, но расположены в других местах Интернета).

После этого браузер объединяет полученные данные. Благодаря этому пользователь может взаимодействовать с одним документом, а не множеством не связанных между собой файлов. Скрипты, которые выполняет браузер, могут принимать дополнительные данные на последующих стадиях обработки страницы (в этом случае программа обновляет страницу для корректного отображения информации).

Топ-30 самых востребованных и высокооплачиваемых профессий 2023

Поможет разобраться в актуальной ситуации на рынке труда

Ультимативный гайд по HTTP. Структура запроса и ответа

Подборка 50+ ресурсов об IT-сфере

Только лучшие телеграм-каналы, каналы Youtube, подкасты, форумы и многое другое для того, чтобы узнавать новое про IT

ТОП 50+ сервисов и приложений от Geekbrains

Безопасные и надежные программы для работы в наши дни

Веб-страница представляет собой гипертекстовый документ. Иными словами, определенные фрагменты текста имеют ссылки, по которым можно перейти на другие страницы. Делается это, как правило, посредством нажатия кнопки мыши. Благодаря этому вы можете путешествовать по Сети. После нажатия на ссылку браузер формирует другой HTTP-запрос и отображает ответ в читабельной форме.

Веб-сервер

Вторым участником обмена является сервер, который необходим для обслуживания пользователя. Именно он предоставляет данные после того, как получает запрос. При этом сервер не всегда является одним единым объектом. Во многих случаях речь идет о совокупности серверов, которые равномерно получают нагрузку от различных пользователей.

Кроме того, иногда предоставлением документов по запросу занимается сложное программное обеспечение, которое опрашивает другие компьютеры. В качестве примера можно привести кеширующие серверы, серверы баз данных, серверы приложений электронной коммерции и т.д.

Ультимативный гайд по HTTP. Структура запроса и ответа

Прокси

Браузер и сервер связываются между собой посредством многочисленных сетевых узлов, которые выступают в качестве передатчиков HTTP сообщений. Из-за слоистой структуры практически всех из них функционируют также на транспортном, сетевом или физическом уровнях. Тем самым они становятся прозрачными на HTTP слое и могут негативно влиять на производительность.

Ультимативный гайд по HTTP. Структура запроса и ответа

Такие операции на уровне приложений называются прокси. Они могут быть как прозрачными, так и непрозрачными (изменяющиеся запросы не будут проходить через них). Прокси выполняют следующие функции:

  • caching (кеш бывает публичным или приватными, как и в случае с браузером);
  • фильтрация (сканирование антивируса, родительский контроль и т.д.);
  • выравнивание нагрузки (позволяют нескольким серверам обрабатывать различные запросы);
  • аутентификация (контроль доступа к разным ресурсам);
  • протоколирование (позволяют сохранять истории операций).

Структура сообщения и методы HTTP

Сообщение HTTP состоит из трех элементов. Они отправляются в определенном порядке:

  • Starting line — стартовая строка. Обуславливает тип передаваемого сообщения.
  • Headers – заголовки. Описывают тело сообщения, особенности его передачи и прочее.
  • Message Body — тело сообщения. Включает в себя ключевую информацию. Стоит упомянуть, что тело сообщения нужно отделить от заголовков пустой строкой.

При этом стартовая строка является обязательным элементом, тогда как заголовки и тело сообщения могут отсутствовать. Дело в том, что стартовая строка определяет тип запроса — ответа. Однако это не относится к сетевому протоколу HTTP версии 0.9. В этом случае сообщение запроса содержит только стартовую строку, а сообщения ответа — лишь тело.

Метод HTTP представляет собой последовательность из различных символов (помимо символов управления и разделителей, указывающих на главное действие над ресурсом). Чаще всего метод состоит из небольшого английского слова, которое записано заголовочными буквами. Название метода чувствительно к регистру.

Сервер имеет возможность использовать любые методы. При этом не существует методов, которые являлись бы обязательными для сервера или клиента. Допустим, что у сервера не получилось определить метод, который указал клиент. В этом случае ему нужно возвратить статус 501 – «Not Implemented». Если же определение прошло успешно, но результат нельзя применить к конкретному ресурсу, то будет отображено сообщение с кодом 405 — «Method Not Allowed».

Так или иначе, сервер должен вставить в ответное сообщение заголовок «Allow».

Ультимативный гайд по HTTP. Структура запроса и ответа

Чтобы получить файл, укажите e-mail:

Подтвердите, что вы не робот,указав номер телефона:

В списке находятся поддерживаемые методы. Любой сервер должен работать с GET и HEAD.

GET — используются для запроса содержимого указанного источника. Данный метод также позволяет начать тот или иной процесс. В этом случае тело сообщения должно содержать в себе сведения об этапе выполнения процесса. В свою очередь, клиент может передать параметры исполнения запроса в URL целевого ресурса сразу после символа «?»: GET/path/resource?.

Ультимативный гайд по HTTP. Структура запроса и ответа

Структура сообщения и методы HTTP

HEAD – используется примерно таким же образом, что и предыдущий вариант. Данный метод отличается лишь тем, что ответ сервера не будет включать в себя тело. Такой запрос применяется с целью извлечения метаданных, проверки существования ресурса (валидация URL). Кроме того, он позволяет понять, имело ли место изменение ресурса после предыдущего запроса. Другой популярный метод — POST.

Про Госуслуги:  Овладейте искусством ввода данных в реестр EGisso для упрощения управления записями.
Оцените статью
ЕГИССО - Вход - egisso.ru
Добавить комментарий