Протокол HTTP, объясненный с помощью Python

Интернет соединяет мир. Но как это работает?

Это сотрудничество различных концепций, технологий и протоколов в аппаратном и программном обеспечении, работающих вместе, таких как DNS, TCP / IP, HTML и другие. В этой истории мы сосредоточимся на деталях одного основного компонента - протокола передачи гипертекста (HTTP).

Почему вам следует потратить 10 минут своей жизни на чтение этой истории? Потому что после прочтения этого…

  • … У вас есть базовое представление о протоколе HTPP
  • … Вы знаете, где используется HTTP
  • … У вас есть некоторый практический опыт, и вы можете следовать предоставленным примерам, используя Python Flask и Python Requests

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

Основы

HTTP - это протокол прикладного уровня, основанный на ресурсах. Он определяет правила взаимодействия между веб-клиентами (в основном браузерами) и веб-серверами и следует модели клиент-сервер. Хорошо ... Что это значит?

Когда вы вводите URL-адрес типа www.medium.com в адресную строку браузера, вы уже используете HTTP. Ваш браузер действует здесь как клиент, запрашивая ресурс (веб-сайт) с веб-сервера, на котором размещен этот веб-сайт. Веб-сервер отвечает на запрос ответом и предоставляет ресурс (например, HTML-файл) обратно клиенту в ответе. Затем клиент визуализирует файл и визуализирует веб-сайт для пользователя.

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

Также всякий раз, когда вы перемещаетесь по странице и переходите на подстраницу (например, щелкаете тему Medium.com или переходите в свой профиль), вы отправляете новый HTTP-запрос. Поскольку протокол HTTP не имеет состояния, сервер не хранит и не хранит никаких данных между двумя запросами.

HTTP используется клиентами не только для запроса веб-сайтов с серверов. Другие варианты использования:

  • предоставление информации от клиента серверу (например, отправка форм, таких как форма входа в систему)
  • REST API
  • Отправленные сервером события, в которых сервер активно передает информацию клиенту.

C компоненты

После введения основных терминов и базового понимания HTTP пора более подробно рассмотреть два основных компонента HTTP - запрос и ответ.

Запрос

Сообщение запроса отправляется от клиента к серверу и содержит следующие элементы.

  • Путь: URL-адрес ресурса сервера, с которым клиент хочет взаимодействовать, например Medium.com. HTTP добавляет очевидную информацию, такую ​​как сам протокол (http: //) и порт (обычно 80)
  • Метод: указывает операцию, которую должен выполнить клиент. Два наиболее часто используемых метода: GET (используется для получения ресурсов / веб-сайта с сервера) и POST ( используется для отправки информации на сервер, например, из формы входа в систему). Щелкните здесь, чтобы увидеть полный список методов HTTP.
  • Версия. Протокол HTTP со временем развивался. HTTP / 1.1 был представлен в 1997 году, за ним последовали HTTP / 2 в 2015 году и HTTP / 3, представленный недавно.
  • Заголовки: (необязательно) используются для отправки на сервер дополнительной информации о клиенте. Стандартный заголовок user-agent t используется для информирования сервера о том, какой браузер использует клиент. Сервер может получить доступ к заголовкам, чтобы адаптировать ответ в соответствии со спецификациями клиента. Заголовков гораздо больше, а сама концепция расширяема и поддерживает настраиваемые заголовки.
  • Body: (необязательно) можно использовать для отправки дополнительного содержимого от клиента на сервер, например имя пользователя и пароль из формы входа, которые должны быть отправлены на сервер

Ответ

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

  • Код состояния: указывает результат запроса - успешно он или нет? 200 OK - стандартный код для успешных сообщений, в то время как 404 Not Found информирует клиента о неправильно указанных или несуществующих ресурсах сервера или 500 Internal Server Error - ошибка логики сервера при обработке запроса. Вы можете найти полный список статусных кодов здесь.
  • Заголовки: содержат дополнительную информацию, передаваемую от сервера клиенту. Стандартный заголовок Content-Language, например, информирует клиента о языке, на котором предоставляется контент. Что касается заголовков запроса, концепция является расширяемой, и можно определить настраиваемые заголовки. .
  • Body: содержит сам запрошенный ресурс, например необработанная версия HTML-документа, которая затем отображается в браузере

E образцы

Ладно, это было чертовски много теории. Давайте посмотрим на несколько примеров. Я опубликовал перечисленные ниже примеры на GitHub, где вы можете загрузить код, запустить собственный веб-сервер на основе Python Flask и поиграть с HTTP-запросами локально.

Я запустил Python Flask Server на своем локальном ПК, используя адрес localhost http://127.0.0.1:5000/

Пример 1: первый успешный запрос GET

Давайте сделаем наш первый запрос по пути / firstrequest, который на стороне сервера определен следующим образом. Всякий раз, когда клиент вызывает этот путь (строка 1), сервер отвечает предоставлением файла index.html (строка 3).

Файл index.html - это простой HTML-файл, содержащий заголовки и абзац.

Когда мы вводим http://127.0.0.1:5000/firstrequest в адресную строку браузера, мы сразу получаем визуализацию страницы. Где материал HTTP? Мы не определили какой-либо метод и не увидели кода статуса в ответе.

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

На этом этапе я бы порекомендовал использовать такой инструмент, как Почтальон. С Postman вы можете детально тестировать HTTP-запросы. Поскольку Postman не является браузером, вы получите ответ в необработанном формате, который предоставляется сервером. Сравните текст ответа ниже с файлом index.html сервера (первый снимок экрана этого примера) - он точно такой же.

Пример 2: Использование заголовка агента пользователя в запросах GET

Хорошо - после настройки нашего первого успешного запроса GET давайте посмотрим, как сервер может использовать заголовки запроса, предоставленные клиентом.

Мы настроили HTTP-запрос на путь / secondrequest, который на стороне сервера определен следующим образом. Всякий раз, когда клиент вызывает этот путь (строка 1), сервер отвечает предоставлением файла start.html (строка 4). Кроме того, он считывает User-Agent из заголовков запроса и пересылает его в файл start.html.

start.html просто прочитает User-Agent из запроса клиента и ответит Я знаю, что вы используете вместе с User-Agent обратно клиенту.

Если вы вызываете путь из браузера Chrome, вы получите следующий ответ…

Если вы используете Edge (надеюсь, нет ;-)), вы получите следующий результат…

И если вы используете Postman, вы получите необработанный ответ вместе с вашим пользовательским агентом.

Пример 3: 404 Not Found - неудачный запрос GET

После успешного выполнения двух запросов давайте смоделируем неуспешный запрос и посмотрим другие ответы с кодом состояния. Если вы вызовете любой путь, который не определен на стороне сервера, вы получите ошибку 404 Not Found в коде состояния ответа сервера. Итак, давайте вызовем путь / randomURLguessing (которого нет на сервере) и проверим ответ. Верно… ресурса не существует. Получаем согласно коду статуса.

Пример 4: 500 Internal Server Error - еще один неудачный запрос GET

Давайте попробуем сгенерировать ошибку на стороне сервера с нашим следующим запросом. Мы собираемся сделать GET-запрос по пути / 4threquest. Если мы проверим кодировку сервера, мы увидим, что сервер попытается преобразовать строку («HI») в int и вернуть результат обратно клиенту с ответом. Как вы понимаете, это не сработает. Невозможно преобразовать строку в число.

Но нам любопытно :-) И действительно, мы получаем ответ - с кодом состояния 500 Internal Server Error. Мы даже получаем дополнительную информацию в ответе сервера, в котором говорится: «ValueError: недопустимый литерал для int () с основанием 10:« HI »». В реальном сценарии сервер не будет предоставлять эту подробную информацию обратно клиенту в случае ошибок, поскольку он может содержать уязвимости безопасности. На продуктивном веб-сервере вы бы предпочли отлавливать эти случаи с помощью обработки исключений и предоставлять более общие ответы.

Пример 5: первый запрос POST

Теперь достаточно ПОЛУЧИТЬ тинг. Давайте вернем что-нибудь на сервер и выполним запрос POST. Мы вызовем путь / thirdrequest, который также принимает сообщения POST (строка 1). Мы сохраняем простоту и возвращаем только то, что клиент предоставил в форме (строка 4).

Мы вызовем путь от Postman и подделаем HTML-форму в теле запроса. После отправки запроса мы получаем ожидаемый ответ.

Пууух ... на сегодня узнал достаточно. Давайте поиграемся с HTTP-запросами!

Спасибо, что прочитали, и с нетерпением ждем ваших отзывов.