request url что это

Библиотека Requests:
эффективные и простые
HTTP-запросы в Python

request url что это. Смотреть фото request url что это. Смотреть картинку request url что это. Картинка про request url что это. Фото request url что это

request url что это. Смотреть фото request url что это. Смотреть картинку request url что это. Картинка про request url что это. Фото request url что это

1. Основные возможности библиотеки Requests

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

Для понимания инструментария библиотеки перечислим ее основные возможности:
– поддержка постоянного HTTP-соединения и его повторное использование;
– применение международных и национальных доменов;
– использование Cookie : передача и получение значений в формате ключ: значение ;
– автоматическое декодирование контента;
SSL верификация;
– аутентификация пользователей на большинстве ресурсов с сохранением;
– поддержка proxy при необходимости;
– загрузка и выгрузка файлов;
– стриминговые загрузки и фрагментированные запросы;
– задержки соединений;
– передача требуемых заголовков на web-ресурсы и др.

В целом, практически любая задача, которая возникает у разработчика, нашла свое отражение в коде библиотеки. Важно понимать, что Requests не предназначен для парсинга ответа сервера (для этого применяют другие модули, например, Beautiful Soup ).

Источник

H Анатомия HTTP-запроса в черновиках

request url что это. Смотреть фото request url что это. Смотреть картинку request url что это. Картинка про request url что это. Фото request url что это

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

Терминология

Для того, чтобы понять, как обрабатывается запрос вам нужно знать следующие определения:

Шаг 1: поиск DNS

На самом деле веб-адреса представляют собой простую строку, которую выглядит как-то так: 216.58.198.174. Если вы перейдете по этому адресу с помощью браузера, то откроется Google. Доменное имя (google.com) это просто псевдоним, который позволяет пользователю легче запомнить адрес.

Итак, когда пользователь вводит доменное имя (например, google.com), браузер делает запрос к DNS и получает IP-адрес, который связан с этим именем.

Думайте о DNS как о телефонной книге. Вместо того, что запоминать номер Вани, вы можете записать его в телефонную книгу. Затем вы можете просто нажать «позвонить Ване» и ваш телефон найдет его номер в базе, и позвонит по этому номеру. В этой аналогии имя «Ваня» — это доменное имя, его номер — это IP-адрес, а телефонная книга — это DNS.

Шаг 2: выполнение запроса

После того, как браузер получил IP-адрес сервера от DNS, он может приступить к созданию запроса. Запрос содержит в себе заголовок и также может содержать тело запроса (например, данные из формы, которую отправил пользователь).

Заголовок содержит в себе следующие параметры:

В итоге запрос будет выглядеть так:

Дополнительная информация может быть добавлена ниже. Они представлены в виде пар ключ/значение, где ключ — это идентификатор, название, а значение — собственно сам кусочек информации. Пример ниже включают в себя информацию о браузере пользователя (user-agent), куки (cookies), тип содержимого (content type), хост (host), которое в данном случае является названием домена и т.д. Полный HTTP-запрос выглядит как-то так:

Шаг 3: ответ сервера

После того, как сервер получил запрос, он генерирует ответ. Так же как и запрос ответ содержит различную информацию, включая:

Обычный ответ сервера выглядит как-то так:

Поле Content-Type говорит, браузеру, какой тип содержимого ему следует ожидать. В данном случае это простой HTML. Таким образом, браузер узнает, что ему нужно отрендерить и показать HTML. Тип содержимого может быть также указан как картинка, видео, JSON и т.д. Это поле говорит браузеру, как нужно обработать полученную информацию.

HTML также подключает различные ресурсы, такие как изображения, видео, шрифты или внешние CSS и JavaScript-файлы. Браузер отправляет запросы к серверу для получения этих ресурсов, а затем размещает их на странице. Если вы откроете инструменты разработчика в Google Chrome (Ctrl+Shift+J) и откроете какой-нибудь сайт, то увидите запросы, которые выполнил браузер (вкладка Network).

request url что это. Смотреть фото request url что это. Смотреть картинку request url что это. Картинка про request url что это. Фото request url что это

Заключение

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

комментарии ( 9 )

Во-первых, для «оригинал тут» есть выбор публикация/перевод.

Во-вторых статей такого вида уже даже на хабре тонна и непонятно зачем этот мусор нужен ещё раз, да ещё и в хабе «программирование».

request url что это. Смотреть фото request url что это. Смотреть картинку request url что это. Картинка про request url что это. Фото request url что это

Это не считая того, что это же написано в help’е: https://habrahabr.ru/info/help/posts/:

Если нажать на слово «Публикацию» во фразе «Хочу опубликовать публикацию», то ниспадающее меню предложит вам выбрать второй доступный для создания вид записи — «Перевод». Механизм создания тот же, что и у публикации, но есть два дополнительных поля — «Автор оригинала» (тут надо указать имя автора оригинального текста) и «Ссылка на оригинал» (здесь — URL страницы оригинала).

Статья очень-очень базовая. На мой взгляд, ее польза несколько сомнительна, но тем не менее, позволю себе оставить пару замечаний.
Мне кажется, что упоминание того, что заголовок Host с доменным именем используется веб-сервером для возможности одновременной работы нескольких веб-ресурсов на одном IP-адресе заслуживает упоминания даже в такой базовой статье. Хотя бы для того, чтобы новичку было понятно, почему при блокировке одного IP блокируются другие сайты, хостящиеся на том же адресе.
«Заголовок» — это на самом деле «строка запроса» (request line), чтобы не создавать путаницы с заголовками (headers), это проблема не перевода, а оригинала. «Пары ключ-значение» — это как раз заголовки.
И еще, мне кажется, что в самых базовых статьях стоит освещать тот факт, что уже 17 лет протокол HTTP/1.1, позволяет не закрывать соединение после каждого запроса-ответа для того чтобы ускорить работу сети, избавившись от затрат на переподключение для каждого ресурса. Для того, чтобы сервер и клиент понимали, когда данные завершились, используется, на мой взгляд один из самых главных заголовков Content-length, значением которого является размер тела сообщения в байтах. Если игнорировать этот заголовок в своих приложениях, даже при указании HTTP/1.1 в строке ответа сервера, соединение будет фактически HTTP/1.0 (Конечно, если не указан Transfer-Encoding, но вот это уже advanced ИМХО) Вообще, последняя спека написана вполне себе человеческим языком и не слишком длинная.

… а что, новичкам можно давать ошибочную информацию?

А почему в ответ на вопрос «что происходит» выбран именно этот уровень абстракции? Почему не разбираются детали TCP/IP соединения? Или HTTPS, которого сейчас много? Или почему не разбирается, что происходит в браузере между моментом нажатия на Enter и отправкой собственно HTTP-запроса?

В конце концов, почему переход на страницу в браузере приравнивается к HTTP-запросу?

+1
Начиная про то, что запрос имён в DNS не такая и простая штука, как кажется, заканчивая тем, что на шаге 2 перед формированием запроса происходит хотя бы банальное подключение к серверу.

Очередная статья, очень низкого уровня, имхо не годная для хабра, а вот для начинающих эникеев/домохозяек сойдет.

> Анатомия HTTP-запроса
И уж точно статью нельзя назвать «Анатомией http», а так — «беглый осмотр веб-технологий»

Время указано в том часовом поясе, который установлен на Вашем устройстве.

Источник

Библиотека Requests в Python

Библиотека requests фактически является стандартом для выполнения HTTP-запросов.

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

Вы узнаете как эффективно использовать запросы и как предотвратить замедление запросов к внешним службам вашего приложения.

Из данного руководства вы узнаете как:

В статье добавлено столько информации, сколько нужно для понимания функций и приведенных примеров.

Для того, чтобы ознакомится с базовыми понятиями работы HTTP-запросов, можно прочитать статью w3schools.

Начало работы с библиотекой requests

Начнем с установки библиотеки запросов. Для этого в консоли выполните команду:

Если вы используете pipenv для управления пакетами python, то выполните команду:

После установки библиотеки, вы можете импортировать ее в приложение:

Теперь, когда всё настроено, самое время начать работать с библиотекой. Первой целью будет научиться как делать GET-запросы.

GET-запросы

HTTP-методы, такие как GET и POST, определяют какое действие вы пытаетесь выполнить при отправке запроса. Помимо GET и POST есть и другие и методы, которые мы будем позже использовать в этой статье.

Поздравляем! Вы сделали первый запрос. Давайте теперь погрузимся немного глубже в ответ на этот запрос.

Объект Response

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

Код ответа HTTP

Например, статус 200 OK означает, что ваш запрос был успешно выполнен, а статус 404 NOT FOUND означает, что ресурс не найден. Есть множество других ответов сервера, которые могут дать вам информацию о том, что произошло с вашим запросом.

.status_code вернул 200 — это значит, что запрос успешно выполнен и сервер отдал вам запрашиваемые данные.

Иногда эту информацию можно использовать в коде для принятия решений:

Поэтому вы можете сделать проще последний пример, переписав if :

Техническая деталь: Этот тест истинного значения возможен благодаря тому, что __bool__() — перегруженный метод в Response.
Это означает, что стандартное поведение Response было переопределено для учета кода состояния (ответа сервера) при опеределении значения истинности.

Например, статус 204 говорит о том, что запрос был успешным, но в теле ответа нет содержимого.

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

Что еще прочитать: Если вы не знакомы f-строками в Python, то я призываю вас воспользоваться ими, так это отличный способ упростить отформатированные строки.

Теперь вы знаете многое о том, что делать с кодом ответа от сервера. Но когда вы делаете GET-запрос, вы редко заботитесь только об ответе сервера — обычно вы хотите увидеть больше.

Далее вы узнаете как просмотреть фактические данные, которые сервер отправил в теле ответа.

Content

Ответ на Get-запрос, в теле сообщения часто содержит некую ценную информацию, известную как «полезная нагрузка» («Payload»). Используя атрибуты и методы Response, вы можете просматривать payload в разных форматах.

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

Заголовки

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

Используя ключ content-type или Content-Type — вы получите одно и то же значение.

Теперь вы узнали основное о Response. Вы увидели его наиболее используемые атрибуты и методы в действии. Давайте сделаем шаг назад и посмотрим как изменяются ответы при настройке Get-запросов.

Параметры строки запроса

Вы даже можете передать значение в байтах:

Строки запроса полезны для параметризации GET-запросов. Вы также можете изменить ваши запросы, добавив или изменив отправляемые вами заголовки.

Заголовки запросов

Заголовок Accept сообщает серверу, какие типы контента может обрабатывать ваше приложение.

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

Другие методы HTTP

В стороне от GET, есть другие популярные методы включая: POST, DELETE, PUT, HEAD, PATCH и OPTIONS. Библиотека Requests предоставляет похожие возможности для работы с каждым из вышеперечисленных методов HTTP:

Каждый вызов функции делает запрос в службу httpbin с использованием соответствующего метода HTTP. Для каждого метода вы можете проверить ответ:

Заголовки, тело ответов, коды состояния и многое другое возвращается в ответе для каждого метода. Далее вы познакомитесь с методами PUT, POST и PATCH и узнаете, чем они отличаются от других типов запросов.

Тело сообщения

Согласно спецификации HTTP — POST, PUT и менее распространенный метод PATCH, передают свои данные через тело сообщения, а не через параметры в строке запроса. Используя эти запросы, вы передатите полезную нагрузку в параметр data соответствующей функции.

Data принимает словарь, список кортежей, байтов или файлоподобный объект.
Вы можете захотеть адаптировать данные, которые отправляете в теле запроса, к конкретным потребностям сервиса, с которым взаимодействуете.

Вы также можете отправить данные в списке кортежей:

Проверка вашего запроса

Когда вы делаете запрос, библиотека requests подготавливает данные, перед тем как отправить их на сервер. Подготовка включает в себя такие вещи, как сериализация JSON и проверка заголовков.

Проверка PreparedRequest дает вам доступ ко всей информации о выполняемом запросе, такой как полезная нагрузка, URL, заголовки, аутенфикация и многое другое.

До сих пор, вы делали много разных видов запросов, но у них всех было одно общее — это неаутентированные запросы к публичным API. Многие службы, с которыми вы можете столкнуться, захотят, чтобы вы каким-то образом идентифицировали себя.

Аутентификация

Одним из примеров API, которые требует аутентификации, является GitHub’s Authenticated User API. Это конечная точка предоставляет информацию о профиле аутентифицированного пользователя. Чтобы сделать запрос к Authenticated User API, вы можете передать свое имя пользователя и пароль в кортеже get() :

Здесь ваш пользовательский механизм TokenAuth получает токен, а затем включает этот токен в заголовок X-TokenAuth вашего запроса.

Проверка SSL-сертификата

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

Хорошей новостью является то, что requests делает это за вас по умолчанию. Однако, в некоторых случаях, вы можете изменить это поведение.

Если вы хотите отключить проверку SSL-сертификата, вы передаете False в параметр verify функции requests :

Библиотека requests даже предупреждает вас, когда вы делаете небезопасный запрос, чтобы помочь сохранить ваши данные в безопасности.

Производительность

Время ожидания

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

В первом запросе, время ожидания истекает через одну секунду. Во втором — через 3,05 секунд.

Вы также можете передать кортеж тайм-ауту. Первый элемент в кортеже является тайм-аутом соединения (время, которое позволяет установить клиенту соединение с сервером), а второй элемент — время ожидания чтения (время ожидания ответа после того, как клиент установил соединение):

Если запрос устанавливает соединение в течение 2 секунд и получает данные в течение 5 секунд после установки соединения, то ответ будет возвращен. Если время ожидания истекло — функция вызовет исключение Timeout :

Ваша программа может перехватить исключение и ответить соответствующим образом.

Объект Session

Сеансы используются для сохранения параметров в запросах. Например, если вы хотите использовать одну и ту же аутентификацию для нескольких запросов, вы можете использовать сеанс:

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

Максимальное количество попыток

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

Когда вы монтируете HTTPAdapter и github_adapter в Session — Session будет придерживаться этой конфигурации в каждом запросе к https://api.github.com.

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

Заключение

Вы прошли долгий путь в изучении мощной библиотеки Requests в Python.

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

Источник

5 Запрос (Request).

Сообщение запроса от клиента к серверу содержит в первой строке: метод, который нужно применить к ресурсу, идентификатор ресурса и используемую версию протокола.

5.1 Строка запроса (Request-Line).

Строка запроса (Request-Line) начинается с лексемы метода, затем следует запрашиваемый URI (Request-URI), версия протокола и CRLF. Эти элементы разделяются SP. В строке запроса (Request-Line) не допустимы CR и LF, исключение составляет конечная последовательность CRLF.

5.1.1 Метод (Method).

Лексема метода указывает метод, который нужно применить к ресурсу, идентифицированному запрашиваемым URI (Request-URI). Метод чувствителен к регистру.

Список методов, применимых к ресурсу, может быть указан в поле заголовка Allow (раздел 14.7). Возврашаемый код состояния ответа всегда сообщает клиенту, допустим ли метод для ресурса в настоящее время, так как набор допустимых методов может изменяться динамически. Серверам СЛЕДУЕТ возвратить код состояния 405 (Метод не дозволен, Method Not Allowed), если метод известен серверу, но не применим для запрошенного ресурса, и 501 (Не реализовано, Not Implemented), если метод не распознан или не реализован сервером. Список методов, известных серверу, может быть указан в поле заголовка ответа Public (раздел 14.35).

Методы GET и HEAD ДОЛЖНЫ поддерживаться всеми универсальными (general-purpose) серверами. Остальные методы опциональны; однако, если вышеупомянутые методы реализованы, то они ДОЛЖНЫ иметь семантику, описанную в разделе 9.

5.1.2 Запрашиваемый URI (Request-URI).

Три опции для запрашиваемого URI (Request-URI) зависят от характера запроса. Звездочка «*» означает, что запрос обращается не к специфическому ресурсу, а к серверу непосредственно, и допускается только в том случае, когда используемый метод не обязательно обращается к ресурсу. В качестве примера:

absoluteURI необходим, когда запрос производится через прокси-сервер. Прокси-сервер перенаправляет запрос на сервер или обслуживает его, пользуясь кэшем, и возвращает ответ. Обратите внимание, что прокси-сервер МОЖЕТ переслать запрос другому прокси-серверу или непосредственно серверу, определенному absoluteURI. Чтобы избежать зацикливания запроса прокси-сервер ДОЛЖЕН быть способен распознавать все имена сервера, включая любые псевдонимы, локальные разновидности, и числовые IP адреса. Request-Line может быть, например, таким:

Чтобы обеспечить переход к absoluteURI во всех запросах в будущих версиях HTTP, все HTTP/1.1 серверы ДОЛЖНЫ принимать absoluteURI в запросах, хотя HTTP/1.1 клиенты будут генерировать их только в запросах к прокси-серверам.

Если прокси-сервер получает запрос без пути в Request-URI, и метод запроса допускает форму запроса «*», то последний прокси-сервер в цепочке запросов ДОЛЖЕН передать запрос, в котором Request-URI равен «*». Например запрос был бы передан прокси-сервером в виде после соединения с портом 8001 хоста «www.ics.uci.edu».

Request-URI передается в формате, определенном в разделе 3.2.1. Первоначальный сервер ДОЛЖЕН декодировать Request-URI, чтобы правильно интерпретировать запрос. Серверам СЛЕДУЕТ отвечать на недопустимые Request-URI соответствующим кодом состояния.

В запросах, которые передаются далее, прокси-сервера никогда НЕ ДОЛЖНЫ перезаписывать часть «abs_path» запрашиваемого URI (Request-URI), за исключением случая, отмеченного выше, когда пустой abs_path заменяется на «*», независимо от внутренней реализации прокси-сервера.

Обратите внимание: правило «ничто не перезаписывать» предохраняет прокси-сервера от изменения значения запроса, в котором первоначальный сервер неправильно использует не зарезервированные символы URL для своих целей. Реализаторам следует знать, что некоторые до-HTTP/1.1 прокси-сервера, как известно, перезаписывали Request-URI.

5.2 Ресурс, идентифицируемый запросом.

Первоначальные HTTP/1.1 сервера ДОЛЖНЫ учитывать, что точный ресурс, идентифицированный интернет-запросом определяется исследованием как Request-URI, так и поля заголовка Host.

Первоначальный сервер, который не позволяет ресурсам отличаться по запрошенному хосту (host), МОЖЕТ игнорировать значение поля заголовка Host. (Но смотрите раздел 19.5.1 для других требований по поддержке Host в HTTP/1.1).

Первоначальный сервер, который различает ресурсы, основанные на запрошенном хосте (иногда называемые виртуальными хостами или vanity hostnames) ДОЛЖЕН использовать следующие правила для определения запрошенного в HTTP/1.1 запросе ресурса:

Получатели HTTP/1.0 запроса, в котором недостает поля заголовка Host, МОГУТ пытаться использовать эвристику (например, исследовать путь в URI на предмет уникальности на каком-либо из хостов) чтобы определить какой точно ресурс запрашивается.

5.3 Поля заголовка запроса.

Поля заголовка запроса позволяют клиенту передавать серверу дополнительную информацию о запросе и о самом клиенте. Эти поля действуют как модификаторы запроса с семантикой, эквивалентной параметрам вызова методов в языках программирования.

Имена полей заголовка запроса (Request-header) могут быть надежно расширены только в сочетании с изменением версии протокола. Однако, новые или экспериментальные поля заголовка могут получить семантику полей заголовка запроса (Request-header), если все стороны соединения распознают их как поля заголовка запроса (Request-header). Нераспознанные поля заголовка обрабатываются как поля заголовка объекта (entity-header).

Источник

Двуликий REQUEST_URI или в поисках корректного HTTP/1.1 сервера

Вы знаете, чем отличается % в Apache mod_rewrite от $_SERVER[«REQUEST_URI»] в PHP?

Для последнего вопроса я и сейчас не смогу предложить решение. Причина в протоколе HTTP/1.1, который пришлось изучить подробнее, когда «изобретал велосипед» (создавал ядро для сайта).

Всё дело в HTTP-заголовке запроса «Host:». При определённых условиях там может быть всё, что угодно, причём сервер должен полностью это проигнорировать согласно HTTP/1.1. Большинство же разработчиков используют значение этого поля, например, для SEO-оптимизаций. Забегая вперёд, скажу, что дополнительный прокси (например, nginx) позволит решить эту проблему.

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

Что же скрывает REQUEST_URI в HTTP/1.1?

Теория

HTTP/1.0

Начну с протокола HTTP/1.0, который описан в RfC1945 www.w3.org/Protocols/rfc1945/rfc1945 и датирован маем 1996 года. Для получения нужной страницы достаточно было подключиться к серверу и отправить одну строку:

При обращении к прокси-серверу необходимо было использовать не абсолютный путь, а полный адрес:

Это всё описано в разделе 5.1.2 «Request-URI».

Появление Host

Чтобы один сервер мог обслуживать сразу несколько доменных имён создатели протокола добавили заголовок запроса «Host:», который должен был содержать домен, к которому идёт обращение. Хотя данный заголовок и не является частью стандарта HTTP/1.0, но некоторыми серверами и клиентами он стал поддерживаться. Например, wget отправляет запросы по протоколу HTTP/1.0, но добавляет «Host:».

HTTP/1.1

A client MUST include a Host header field in all HTTP/1.1 request messages. If the requested URI does not include an Internet host name for the service being requested, then the Host header field MUST be given with an empty value.

Кроме этого значительные изменения коснулись Request-URI из строки запросов (раздел 5.1.2). Как и в предыдущем протоколе полный адрес требуется при запросах к прокси серверам («The absoluteURI form is REQUIRED when the request is being made to a proxy.»). Но отвечать на подобные запросы должны все сервера, хотя оформлять подобные запросы клиенты будут лишь к прокси серверам:

To allow for transition to absoluteURIs in all requests in future versions of HTTP, all HTTP/1.1 servers MUST accept the absoluteURI form in requests, even though HTTP/1.1 clients will only generate them in requests to proxies.

Обращаю внимание, что предполагался переход на полные адреса (absoluteURI, например, http://www.w3.org/pub/WWW/TheProject.html), поэтому от клиентов не требуется обязательного использования лишь абсолютных путей (abs_path, например, /pub/WWW/TheProject.html). Кроме того, от сервера в явном виде требуется умение отвечать на запросы клиентов с absoluteURI, поэтому возражение, что в данном случае запрос клиента не является корректным, исключаю сразу, поскольку «клиент всегда прав».

Host в HTTP/1.1

Изменения в Request-URI могут показаться безобидными, но раздел 5.2 содержит одно важное требование: «If Request-URI is an absoluteURI, the host is part of the Request-URI. Any Host header field value in the request MUST be ignored.» То есть интерпретация запроса

должна совпадать с запросом

Вы игнорируете «Host:» при запросах с absoluteURI?

THE_REQUEST
The full HTTP request line sent by the browser to the server (e.g., «GET /index.html HTTP/1.1»). This does not include any additional headers sent by the browser. This value has not been unescaped (decoded), unlike most other variables below.

REQUEST_URI
The path component of the requested URI, such as «/index.html». This notably excludes the query string which is available as as its own variable named QUERY_STRING.

То есть в % всегда будет абсолютный путь и никогда полного адреса.

Попробуйте стандартную SEO задачу по добавлению «www» к домену без него решить с помощью mod_rewrite, если пользователь отправит следующий запрос:

Вначале статьи спрашивал про отличие % в Apache mod_rewrite от $_SERVER[«REQUEST_URI»] в PHP, поэтому приведу выдержку из документации к PHP:

REQUEST_URI
The URI which was given in order to access this page; for instance, ‘/index.html’.

Может быть это где-нибудь и настраивается, но у меня PHP/5.3.13 возвращает absoluteURI при запросе с полным адресом.

Практика

Давайте теперь рассмотрим, что же происходит при запросах к реальным серверам. Адреса сайтов взял со страницы компаний Хабра (там список меняется, брал в конце прошлой недели). Набросал небольшой скрипт на Node.JS, в котором функция http_check отправляет одиночные запросы, а full_http_check формирует к одному серверу несколько запросов по определённым шаблонам.

Теперь рассмотрим подробнее каждый из шаблонов и реакцию сайтов.

Запрос 1

Самый распространённый вариант запроса HTTP/1.1, включающий абсолютный путь и правильный заголовок Host. На него должен корректно отвечать любой сервер, то есть ждём «HTTP/1.1 200 OK».

Все сервера вернули «HTTP/1.1 200 OK». Ниже представлена таблица значений заголовка ответа «Server»:

КомпанияЗаголовок «Server:»
Apps4Allnginx/1.0.15
Badoonginx
Box Overviewnginx/1.2.1
DevConfnginx/1.0.15
e-Legion Ltd.nginx/1.0.5
IBMIBM_HTTP_Server
IntelMicrosoft-IIS/7.5
JetBrainsnginx
KolibriOS Project Teamlighttpd/1.4.32
Mail.Ru Groupnginx/1.2.5
MicrosoftMicrosoft-IIS/7.5
Opera Software ASAnginx
Rusonyxnginx
UIDGApache
Zfort Groupnginx/1.4.1
ВымпелКом (Билайн)Microsoft-IIS/7.5
Мосиграnginx/1.4.1
Нордавиндnginx/1.0.4
Яндексnginx/1.2.1

Запрос 2

Вариант первого типа запросов, но вместо абсолютного пути указываем полный адрес.

В ответ на этот запрос все сервера опять проявили единодушие. «Лёгкие» запросы разбирать каждый сервер умеет.

Запрос 3

Запрос на HTTP/1.0 с абсолютным путём, без «Host:». Должны получить «HTTP/1.0 200 OK».

На третьем запросе сервера «посыпались». И нет ни одного ответа «HTTP/1.0 200 OK».

КомпанияОтвет сервера
Apps4AllHTTP/1.1 301 Moved Permanently
BadooHTTP/1.1 302 Moved Temporarily
Box OverviewHTTP/1.1 200 OK
DevConfHTTP/1.1 404 Not Found
e-Legion Ltd.HTTP/1.1 301 Moved Permanently
IBMHTTP/1.1 200 OK
IntelHTTP/1.0 400 Bad Request
JetBrainsHTTP/1.1 301 Moved Permanently
KolibriOS Project TeamHTTP/1.0 404 Not Found
Mail.Ru GroupHTTP/1.1 200 OK
MicrosoftHTTP/1.1 200 OK
Opera Software ASAHTTP/1.1 404 Not Found
RusonyxHTTP/1.1 301 Moved Permanently
UIDGHTTP/1.1 404 Not Found
Zfort GroupHTTP/1.1 404 Not Found
ВымпелКом (Билайн)HTTP/1.1 302 Redirect
МосиграHTTP/1.1 404 Not Found
НордавиндHTTP/1.1 200 OK
ЯндексHTTP/1.1 404 Not Found

Запрос 4

Предыдущий запрос, но добавим «Host:». От первого запроса отличается лишь версией протокола.

Очень положительным образом подействовал Host на сервера — у всех ответ «200 OK», но HTTP/1.0 был лишь у следующих: Intel и KolibriOS Project Team.

Запрос 5

Запрос на HTTP/1.0 с полным адресом, без «Host:». Было бы здорово прочитать «HTTP/1.0 200 OK».

Картина полностью совпадает с результатами предыдущего запроса, но вот e-Legion Ltd. выдал «HTTP/1.1 500 INTERNAL SERVER ERROR».

Запрос 6

Предыдущий запрос, но добавим «Host:». От второго запроса отличается лишь версией протокола.

Результаты полностью совпадают с четвёртым запросом, то есть «Host:» исправил внутреннюю ошибку у сервера e-Legion Ltd.

Запрос 7

Вариант второго запроса с полным адресом, но в «Host:» запишем несуществующий поддомен. Запрос абсолютно корректный, поэтому сервер должен отвечать «HTTP/1.1 200 OK».

Запрос 8

Теперь в качестве «Host:» укажем несуществующий домен. В запросе ничего не изменилось, но некоторым серверам это может уже не понравиться.

Запрос 9

Заголовок «Host:» должен полностью игнорироваться, поэтому запишем произвольный текст, которому позавидуют многие пароли. По стандарту будем ожидать «HTTP/1.1 200 OK».

На запросы 7-9 сервера отвечали одинаково следующим образом:

КомпанияОтвет сервераЗаголовок «Server:»
Apps4AllHTTP/1.1 200 OKnginx/1.0.15
BadooHTTP/1.1 200 OKnginx
Box OverviewHTTP/1.1 200 OKnginx/1.2.1
DevConfHTTP/1.1 500 Internal Server Errornginx/1.0.15
e-Legion Ltd.HTTP/1.1 500 INTERNAL SERVER ERRORnginx/1.0.5
IBMHTTP/1.1 200 OKIBM_HTTP_Server
IntelHTTP/1.0 400 Bad RequestAkamaiGHost
JetBrainsHTTP/1.1 200 OKnginx
KolibriOS Project TeamHTTP/1.1 200 OKlighttpd/1.4.32
Mail.Ru GroupHTTP/1.1 200 OKnginx/1.2.5
MicrosoftHTTP/1.1 200 OKMicrosoft-IIS/7.5
Opera Software ASAHTTP/1.1 200 OKnginx
RusonyxHTTP/1.1 200 OKnginx
UIDGHTTP/1.1 200 OKApache
Zfort GroupHTTP/1.1 200 OKnginx/1.4.1
ВымпелКом (Билайн)HTTP/1.1 200 OKMicrosoft-IIS/7.5
МосиграHTTP/1.1 200 OKnginx/1.4.1
НордавиндHTTP/1.1 200 OKnginx/1.0.4
ЯндексHTTP/1.1 200 OKnginx/1.2.1

Запрос 10

Первый из неправильных запросов. Отправим правильный «Host:», но в полном адресе добавим несуществующий поддомен.

Поскольку начались запросы с ошибками, то результаты пугать не должны.

КомпанияОтвет сервера
Apps4AllHTTP/1.1 301 Moved Permanently
BadooHTTP/1.1 301 Moved Permanently
Box OverviewHTTP/1.1 200 OK
DevConfHTTP/1.1 404 Not Found
e-Legion Ltd.HTTP/1.1 301 Moved Permanently
IBMHTTP/1.1 200 OK
IntelHTTP/1.1 200 OK
JetBrainsHTTP/1.1 301 Moved Permanently
KolibriOS Project TeamHTTP/1.1 404 Not Found
Mail.Ru GroupHTTP/1.1 200 OK
MicrosoftHTTP/1.1 200 OK
Opera Software ASAHTTP/1.1 404 Not Found
RusonyxHTTP/1.1 301 Moved Permanently
UIDGHTTP/1.1 404 Not Found
Zfort GroupHTTP/1.1 404 Not Found
ВымпелКом (Билайн)HTTP/1.1 302 Redirect
МосиграHTTP/1.1 301 Moved Permanently
НордавиндHTTP/1.1 200 OK
ЯндексHTTP/1.1 404 Not Found

Почти треть серверов не стала тратить время на попытку подсказать правильный путь (перенаправить). К сожалению, многие сервера просто перенаправляют на главную страницу.

Запрос 11

Теперь попробуем отправить несуществующий домен.

Здесь результаты полностью совпадают с предыдущим запросом, но Мосигра вместо «HTTP/1.1 301 Moved Permanently» выдала уже «HTTP/1.1 404 Not Found».

Запрос 12

А сработает ли вообще произвольный текст в качестве домена?

Ответ «HTTP/1.1 200 OK» пришёл от Intel и Opera Software ASA. IBM и Мосигра вернули «HTTP/1.1 404 Not Found». Все остальные написали 404 Bad Request, причём часть вообще без заголовка (возможный вариант в HTTP/1.0).

Запрос 13

Копия одинадцатого запроса, но ещё и с поддоменом в качестве «Host:». Вряд ли имеет смысл проверять другие некорректные комбинации.

Результаты тоже стали копией запроса 11, но сдался Intel и вернул «HTTP/1.0 400 Bad Request».

Запрос 14

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

Оказалось, что довольно много сайтов воспринимают протокол HABR:

КомпанияОтвет сервера
Apps4AllHTTP/1.1 200 OK
BadooHTTP/1.1 200 OK
Box OverviewHTTP/1.1 200 OK
DevConfHTTP/1.1 200 OK
e-Legion Ltd.HTTP/1.1 200 OK
IBMHTTP/1.1 200 OK
IntelHTTP/1.0 400 Bad Request
JetBrainsHTTP/1.1 200 OK
KolibriOS Project TeamHTTP/1.1 301 Moved Permanently
Mail.Ru GroupHTTP/1.1 200 OK
MicrosoftHTTP/1.1 400 Bad Request
Opera Software ASAHTTP/1.1 400 BAD_REQUEST
RusonyxHTTP/1.1 200 OK
UIDGHTTP/1.1 200 OK
Zfort GroupHTTP/1.1 200 OK
ВымпелКом (Билайн)HTTP/1.1 400 Bad Request
МосиграHTTP/1.1 400 BAD_REQUEST
НордавиндHTTP/1.1 200 OK
ЯндексHTTP/1.1 200 OK

Запрос 15

Попробуем окончательно сломить сопротивление сервера и отправим предыдущий запрос, но с некорректным поддоменом.

Результаты похожи на десятый запрос, но есть и изменения:

КомпанияЗапрос 10Запрос 15
Apps4AllHTTP/1.1 301 Moved PermanentlyHTTP/1.1 301 Moved Permanently
BadooHTTP/1.1 301 Moved PermanentlyHTTP/1.1 301 Moved Permanently
Box OverviewHTTP/1.1 200 OKHTTP/1.1 200 OK
DevConfHTTP/1.1 404 Not FoundHTTP/1.1 404 Not Found
e-Legion Ltd.HTTP/1.1 301 Moved PermanentlyHTTP/1.1 301 Moved Permanently
IBMHTTP/1.1 200 OKHTTP/1.1 200 OK
IntelHTTP/1.1 200 OKHTTP/1.0 400 Bad Request
JetBrainsHTTP/1.1 301 Moved PermanentlyHTTP/1.1 301 Moved Permanently
KolibriOS Project TeamHTTP/1.1 404 Not FoundHTTP/1.1 301 Moved Permanently
Mail.Ru GroupHTTP/1.1 200 OKHTTP/1.1 200 OK
MicrosoftHTTP/1.1 200 OKHTTP/1.1 400 Bad Request
Opera Software ASAHTTP/1.1 404 Not FoundHTTP/1.1 400 BAD_REQUEST
RusonyxHTTP/1.1 301 Moved PermanentlyHTTP/1.1 301 Moved Permanently
UIDGHTTP/1.1 404 Not FoundHTTP/1.1 404 Not Found
Zfort GroupHTTP/1.1 404 Not FoundHTTP/1.1 404 Not Found
ВымпелКом (Билайн)HTTP/1.1 302 RedirectHTTP/1.1 400 Bad Request
МосиграHTTP/1.1 301 Moved PermanentlyHTTP/1.1 400 BAD_REQUEST
НордавиндHTTP/1.1 200 OKHTTP/1.1 200 OK
ЯндексHTTP/1.1 404 Not FoundHTTP/1.1 404 Not Found

Запрос 16

Попробуем использовать произвольный домен.

Результаты совпали с предыдущим запросом.

Запрос 17

И в третий раз попробуем заменить домен на произвольный текст.

Уже ни одного положительного ответа от сервера. По сравнению с запросом 12 изменения есть у следующих сайтов:

КомпанияЗапрос 12Запрос 17
IntelHTTP/1.1 200 OKHTTP/1.0 400 Bad Request
KolibriOS Project TeamHTTP/1.1 400 Bad RequestHTTP/1.1 301 Moved Permanently
Opera Software ASAHTTP/1.1 200 OKHTTP/1.1 400 BAD_REQUEST
МосиграHTTP/1.1 404 Not FoundHTTP/1.1 400 BAD_REQUEST

Запрос 18

А теперь попробуем избавиться и от корректного заголовка «Host:».

Всего одно изменение по сравнению с предыдущим результатом — сервер KolibriOS Project Team стал возвращать «HTTP/1.1 404 Not Found» вместо «HTTP/1.1 301 Moved Permanently».

Запрос N

Напишите, если хотите попробовать какие-нибудь ещё варианты запросов. А можете сделать это и сами.

Заключение

Попробуем подвести некоторые итоги. Почти все рассмотренные сервера корректно отвечали на HTTP/1.1 запросы. Исключение составили DevConf, e-Legion Ltd. и Intel. Первые два используют nginx, поэтому проблема, скорее всего, именно в его настройке. Intel же использует AkamaiGHost, который либо неправильно настроен, либо плохо поддерживает HTTP/1.1. Допускаю, что одной из причин корректного прохождения тестов является именно nginx (его использовали 14 из 19 серверов). Из-за разницы в версиях обнаружилась цепочка из nginx/1.0.10 и nginx/1.4.1 у UIDG.

Считаете, что всё просто? Попробуйте настроить Apache с учётом SEO так, чтобы он корректно обрабатывал запросы с ошибочным «Host:» и основывался лишь на полном адресе в строке запроса.

Какой практический смысл от «неправильных» корректных запросов? Сомневаюсь, что получится найти какую-нибудь уязвимость. Но неужели почти за пятнадцать лет никто не научился создавать корректные HTTP/1.1 сервера?

P.S. Помните про различия между % в Apache mod_rewrite и $_SERVER[«REQUEST_URI»] в PHP.

Запрос 19

По совету AEP взял второй запрос, но к хосту добавил ещё нулевой байт и некоторую строку. Тут зависело от того, насколько хорошо сервер будет игнорировать хост с нулевым байтом.

В скрипт добавил следующий шаблон:

Все сервера вернули «HTTP/1.1 400 Bad Request», кроме IBM, Opera Software ASA и Мосигра.
Когда попробовал нулевой байт добавить в запрос, то кроме IBM и Opera Software все сообщили об ошибке 400.

Источник

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *