request uri без параметров
URI — сложно о простом (Часть 1)
Появилось таки некоторое количество времени, и я решил написать сий пост, идея которого возникла уже давно.
Связан он будет будет с такой, казалось бы, простой вещью, как URI, детальному рассмотрению которой в рунете уделяется как-то мало внимания.
«Пфф, ссылки они и в Африке ссылки, чего тут разбираться?» — скажете вы, тогда я задам вопрос:
Перед тем как начать хотел бы обозначить, что есть пост на схожую тему, в котором все обозначено проще и немного понятнее. Целью же этого поста, я ставлю более глубокое изучение вопроса и сбор информации об URI в одном месте, дабы «не потерять». Ну, почти в одном месте, статья будет разделена на две части
А для удобства бахнем оглавление, которое работает не без особенностей URI, которую мы рассмотрим попозжа, в этой статье.
Ознакомление
1. URI
Унифицированный Идентификатор Ресурса, в простонародье — URI
Самое свежее описание того, чем же все-таки являются эти пресловутые URI датируется январем аж 2005-го, а именно RFC3986, написанный самим Тимом Бёнесом-Ли, родоначальника всеми нами любимого тырнета.
Резюмируя п.1.1 можно сформулировать определение:
Многие из вас замечали, что на разных ресурсах ссылки называют то URL, то URI и, вероятно, становилось интересно — какой же из вариантов правильный?
Дело в том, что URL увидел свет и был документирован в 1990 году, в то время как URI был документирован лишь в 1994 году. И вплоть до 2002 года, до выхода RFC3305, уместными были оба варианта именования, что, порой вносило путаницу.
В п.2 RFC3305 сообщается об устаревании такого термина как URL, применимо к ссылкам, и что отныне верным будет именование URI, с того момента, во всех документах W3C использует термин URI. Исходя из этого, применяя термин URL к соответствующим ссылкам, вы не делаете смысловой ошибки, но делаете ее с точки зрения правильного именования.
Так же примечателен тот момент, что вплоть до выхода RFC2396, в 1997 году, URI расшифровывался как Universal Resource Identifier, что можно увидеть в RFC1630
1.1. Синтаксис
URI составлен из ограниченного набора символов, состоящих из цифр, букв и нескольких графических символов, все эти символы вписываются в кодировку US-ASCII (ASCII). Зарезервированное подмножество символов может использоваться, чтобы разграничить компоненты синтаксиса в URI, в то время как остающиеся символы: не зарезервированный набор и включая те зарезервированные символы, которые не действуют как разделители в данной компоненте URI, определяют данные идентификации каждого компонента.
Зарезервированные символы
Не зарезервированные символы
Для данного случая, согласно ABNF :
ALPHA — любая буква верхнего и нижнего регистров кодировки ASCII (в regExp [A-Za-z])
DIGIT — любая цифра (в regExp 8)
HEXDIG — шестнадцатиричная цифра (в regExp [0-9A-F])
Процентное кодирование
Т.о., %20, например, означает пробел.
1.2. Компоненты URI
где в квадратных скобках опциональные компоненты
Переходя по указанной в оглавлении ссылке, браузер производит переход ко вторичному ресурсу относительно данной страницы, т.е. скроллит вниз, до появления нужного на экране.
На этом, пожалуй, знакомство с URI можно закончить и начать углубляться в отдельные подвиды URI, а именно
2. URL
URL используются, чтобы определить местоположение ресурсов, обеспечивая абстрактную идентификацию расположения ресурса. Определив местоположение ресурса, система может выполнить множество операций на ресурсе, которые могут быть характеризованы такими словами как ‘доступ’, ‘обновление’, ‘замена’, ‘поиск атрибутов’. В целом только метод доступа должен быть определен для любой схемы URL.
2.1. Структура
В целом, URL имеет схожую структуру, для всех схем, хотя для каждой отдельно взятой схемы, структура может отличаться от общего шаблона.
Графически ее можно выразить в следующем виде:
3. URN
Унифицированные имена ресурсов (URN) предназначены, чтобы служить постоянными, независимыми от расположения, идентификаторами ресурсов и разработаны для упрощения отображения других пространств имен (которые совместно используют свойства URN) в URN-пространство. Таким образом, синтаксис URN обеспечивает средство закодировать символьные данные в форме, которая может быть отправлена посредством существующих протоколов, записана при помощи большинства клавиатур, и т.д.
3.1. Структура
Самоидентифицирующийся URN
Такие URN содержат в NID название хэш-функции, а в NSS значение хэша, вычисленного для идентифицируемого объекта. Такие ссылки используются в magnet-ссылках и заголовках p2p-сети Gnutela2.
Например, URN из magnet-ссылки с одного торрент-трекера:
magnet:?xt=urn:btih:c68abc1ba9b8c7c4bc373862cad1a8c01d69e53d.
С теорией все, во второй части рассмотрим, что можно и что нужно делать с URI, если мы их обрабатываем, а именно — нормализация, разбор и т.д.
За сим откланяюсь, спасибо что читали, надеюсь не было скучно, удачи!
Строка запроса без аргументов GET в PHP
Затем добавьте имя хоста и протокол.
Лучший ответ здесь – от RiaD :
Stackoverflow: как удалить запрос и получить только URL?
Вы можете использовать strtok для получения строки до первого появления?
Это приложение strtok для возврата всего в строку до первого экземпляра символа будет работать лучше, чем любой другой метод в PHP, хотя WILL оставит запрос в памяти.
Самое простое решение:
echo parse_url ($_SERVER[«REQUEST_URI»], PHP_URL_PATH);
Я на самом деле думаю, что это не лучший способ разобрать его. Это не чисто или немного из-за темы …
Я бы сделал что-то вроде …
РЕДАКТИРОВАТЬ
Почему так сложно? знак равно
это должно действительно сделать это человек;)
Вот решение, которое учитывает разные порты и https:
Или более базовое решение, которое не учитывает другие порты:
Не всем это будет просто, но я считаю, что это лучший способ обойти это:
То, что происходит, это просто пройти через REQUEST_URI с начала строки, а затем остановиться, когда он попадет в «?» (что действительно, только должно произойти, когда вы добираетесь до параметров).
Я надеюсь, что кто-то сможет это использовать …
PS. Это подтверждено, работая при использовании SLIM, чтобы перенаправить URL-адрес.
У меня была такая же проблема, когда мне нужна ссылка на домашнюю страницу. Я пробовал это, и это сработало:
Обратите внимание на знак вопроса в конце. Я считаю, что говорит, что машина перестает думать от имени кодера 🙂
Website-create.ru
Сегодня поговорим о том, как получить адрес страницы в php.
Зачем это может быть нужно?
Сценарии могут быть разными. Например, у нас используется один и тот же шаблон для разных разделов. Но в одном из разделов нам необходимо вывести (или не вывести) какой-то специфичный блок, которого в других разделах быть не должно.
Вероятно мы захотим сделать это по условию. И именно в условии мы и будем проверять тот ли это раздел.
Возможно с архитектурной точки зрения — это не самое лучшее решение. Однако, очень часто нам достаются уже готовые проекты, с которыми нужно что-то делать.
Получаем URL текущей страницы
Если вы хотите посмотреть всё, что хранит этот массив, то можете воспользоваться следующим кодом, который в читабельном виде выведет все значения:
Итак, давайте представим, что у нас есть веб страница следующего вида: http://localhost/php-lessons/url/?name=anna&city=Valencia.
Я тестирую на локальном сервере. Когда вы будете работать с реальным сайтом, который лежит в сети, то вместо localhost у вас будет имя вашего сайта (например exmple.ru).
Что мы видим в нашем подопытном url?
Давайте разберемся с каждой ситуацией.
Получаем полный URL страницы в php
Чтобы получить полный URL страницы вместе с GET-параметрами, воспользуемся следующим кодом:
Сначала мы проверяем, какой протокол используется: https или http.
Далее мы присоединяем двоеточие и 2 слэша, имя домена (хоста) и остальную часть нашего URL.
Результат будет вот таким:
Если протокол нам получать не нужно, то можно сократить код до такого:
Результат тогда будет следующим:
Получаем URL страницы без GET-параметров в php
Иногда нас не интересуют GET-параметры, которые передаются как часть URL, и нам нужно получить адрес без них.
GET-параметры в нашем случает — это name=anna&city=Valencia
Чтобы отсечь их мы можем использовать php-функцию explode, которая разбивает строку по разделителю.
Наш URL — это ни что иное, как строка. GET-параметры всегда начинают передаваться после знака «?». Следовательно разделителем будет вопросительный знак.
Функция explode превратит строку в массив с двумя элементами. В первом будет содержаться наш искомый url без GET-параметров, а во втором останутся GET-параметры.
Результат будет таким: http://localhost/php-lessons/url/
Получаем GET-параметры из URL
Здесь совсем все просто. Чтобы получить только GET-параметры будем использовать следующий код:
Дальше мы можете разобрать это строку, например, с помощью функции explode или сделать с ними что-либо еще (в зависимости от стоящей перед вами задачи).
А у меня на сегодня всё!
Ставьте лайки, оставляйте комментарии, подписывайтесь на обновления!
В этой статье будет рассказано о том, как в языке программирования PHP получить адрес текущей страницы. Также вы узнаете о работе переменной $_SERVER.
Первое, о чём следует сказать, — зачем вообще получать ссылки (urls) в PHP? На практике варианты могут различаться. Представьте, что у нас для разных разделов применяется один и тот же шаблон. И возникает потребность в том, чтобы вывести (либо не вывести — зависит от ситуации) какой-нибудь специальный блок, причём в других разделах вывод этого блока не нужен.
В большинстве случаев мы пожелаем выполнить поставленную задачу по условию. То есть сделаем условие, в котором будем выполнять проверку того либо иного раздела. Можно сказать, что с точки зрения архитектуры данное решение не является оптимальным. Но на практике нам нередко достаются уже реализованные проекты, с которыми необходимо что-то решать с учётом уже имеющейся архитектуры.
Но давайте не будем много говорить, а лучше приступим к решению поставленной задачи — получению ссылки в PHP.
Получение ссылки текущей страницы в PHP
Идём дальше. Представьте, что у вас есть web-страница, имеющая следующий вид: http://localhost/php-lessons/url/?name=anna&city=Valencia. Тестирование в данном примере осуществляется на локальном сервере. Если надо тестировать код на реальном веб-сайте, доступном в интернете, достаточно вместо localhost прописать имя сайта (домен) — тот же otus.ru.
Что же мы увидим в подопытном url? Нас могут интересовать следующие данные: — адрес веб-страницы без GET-параметров; — URL с GET-параметрами; — непосредственно GET-параметры без текущей ссылки (адреса веб-страницы).
Лучше всего разобраться с каждым из случаев по отдельности — так будет гораздо понятнее.
Получение полного URL в PHP
Для получения полного URL вместе с имеющимися GET-параметрами, пригодится следующий код:
На втором этапе выполняется присоединение двоеточия и двух слэшев, имени домена и остальной части URL.
Итог выполнения кода будет следующим:
Если протокол получать не требуется, код на PHP можно немного сократить:
Смотрим на результат и видим, что протокол отсутствует:
Получение URL в PHP без GET-параметров
Иногда эти параметры, передаваемые в качестве части ссылки, нас не интересуют, то есть требуется получить адрес без них. Мы говорим о следующих параметрах: name=anna&city=Valencia.
В действительности их можно отсечь, используя функцию explode в PHP, разбивающую строку по разделителю. Не стоит объяснять, что ссылка представляет собой строку, а параметры GET начинают прописываться после «?». В результате вопросительный знак и станет разделителем, а функция explode сделает из строки массив с 2-мя элементами. Первый элемент станет содержать искомую ссылку без GET-параметров, так как эти самые параметры останутся во втором элементе.
Получение только параметров GET
С помощью этого кода получим:
Двуликий 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:» |
---|---|
Apps4All | nginx/1.0.15 |
Badoo | nginx |
Box Overview | nginx/1.2.1 |
DevConf | nginx/1.0.15 |
e-Legion Ltd. | nginx/1.0.5 |
IBM | IBM_HTTP_Server |
Intel | Microsoft-IIS/7.5 |
JetBrains | nginx |
KolibriOS Project Team | lighttpd/1.4.32 |
Mail.Ru Group | nginx/1.2.5 |
Microsoft | Microsoft-IIS/7.5 |
Opera Software ASA | nginx |
Rusonyx | nginx |
UIDG | Apache |
Zfort Group | nginx/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».
Компания | Ответ сервера |
---|---|
Apps4All | HTTP/1.1 301 Moved Permanently |
Badoo | HTTP/1.1 302 Moved Temporarily |
Box Overview | HTTP/1.1 200 OK |
DevConf | HTTP/1.1 404 Not Found |
e-Legion Ltd. | HTTP/1.1 301 Moved Permanently |
IBM | HTTP/1.1 200 OK |
Intel | HTTP/1.0 400 Bad Request |
JetBrains | HTTP/1.1 301 Moved Permanently |
KolibriOS Project Team | HTTP/1.0 404 Not Found |
Mail.Ru Group | HTTP/1.1 200 OK |
Microsoft | HTTP/1.1 200 OK |
Opera Software ASA | HTTP/1.1 404 Not Found |
Rusonyx | HTTP/1.1 301 Moved Permanently |
UIDG | HTTP/1.1 404 Not Found |
Zfort Group | HTTP/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:» |
---|---|---|
Apps4All | HTTP/1.1 200 OK | nginx/1.0.15 |
Badoo | HTTP/1.1 200 OK | nginx |
Box Overview | HTTP/1.1 200 OK | nginx/1.2.1 |
DevConf | HTTP/1.1 500 Internal Server Error | nginx/1.0.15 |
e-Legion Ltd. | HTTP/1.1 500 INTERNAL SERVER ERROR | nginx/1.0.5 |
IBM | HTTP/1.1 200 OK | IBM_HTTP_Server |
Intel | HTTP/1.0 400 Bad Request | AkamaiGHost |
JetBrains | HTTP/1.1 200 OK | nginx |
KolibriOS Project Team | HTTP/1.1 200 OK | lighttpd/1.4.32 |
Mail.Ru Group | HTTP/1.1 200 OK | nginx/1.2.5 |
Microsoft | HTTP/1.1 200 OK | Microsoft-IIS/7.5 |
Opera Software ASA | HTTP/1.1 200 OK | nginx |
Rusonyx | HTTP/1.1 200 OK | nginx |
UIDG | HTTP/1.1 200 OK | Apache |
Zfort Group | HTTP/1.1 200 OK | nginx/1.4.1 |
ВымпелКом (Билайн) | HTTP/1.1 200 OK | Microsoft-IIS/7.5 |
Мосигра | HTTP/1.1 200 OK | nginx/1.4.1 |
Нордавинд | HTTP/1.1 200 OK | nginx/1.0.4 |
Яндекс | HTTP/1.1 200 OK | nginx/1.2.1 |
Запрос 10
Первый из неправильных запросов. Отправим правильный «Host:», но в полном адресе добавим несуществующий поддомен.
Поскольку начались запросы с ошибками, то результаты пугать не должны.
Компания | Ответ сервера |
---|---|
Apps4All | HTTP/1.1 301 Moved Permanently |
Badoo | HTTP/1.1 301 Moved Permanently |
Box Overview | HTTP/1.1 200 OK |
DevConf | HTTP/1.1 404 Not Found |
e-Legion Ltd. | HTTP/1.1 301 Moved Permanently |
IBM | HTTP/1.1 200 OK |
Intel | HTTP/1.1 200 OK |
JetBrains | HTTP/1.1 301 Moved Permanently |
KolibriOS Project Team | HTTP/1.1 404 Not Found |
Mail.Ru Group | HTTP/1.1 200 OK |
Microsoft | HTTP/1.1 200 OK |
Opera Software ASA | HTTP/1.1 404 Not Found |
Rusonyx | HTTP/1.1 301 Moved Permanently |
UIDG | HTTP/1.1 404 Not Found |
Zfort Group | HTTP/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:
Компания | Ответ сервера |
---|---|
Apps4All | HTTP/1.1 200 OK |
Badoo | HTTP/1.1 200 OK |
Box Overview | HTTP/1.1 200 OK |
DevConf | HTTP/1.1 200 OK |
e-Legion Ltd. | HTTP/1.1 200 OK |
IBM | HTTP/1.1 200 OK |
Intel | HTTP/1.0 400 Bad Request |
JetBrains | HTTP/1.1 200 OK |
KolibriOS Project Team | HTTP/1.1 301 Moved Permanently |
Mail.Ru Group | HTTP/1.1 200 OK |
Microsoft | HTTP/1.1 400 Bad Request |
Opera Software ASA | HTTP/1.1 400 BAD_REQUEST |
Rusonyx | HTTP/1.1 200 OK |
UIDG | HTTP/1.1 200 OK |
Zfort Group | HTTP/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 |
---|---|---|
Apps4All | HTTP/1.1 301 Moved Permanently | HTTP/1.1 301 Moved Permanently |
Badoo | HTTP/1.1 301 Moved Permanently | HTTP/1.1 301 Moved Permanently |
Box Overview | HTTP/1.1 200 OK | HTTP/1.1 200 OK |
DevConf | HTTP/1.1 404 Not Found | HTTP/1.1 404 Not Found |
e-Legion Ltd. | HTTP/1.1 301 Moved Permanently | HTTP/1.1 301 Moved Permanently |
IBM | HTTP/1.1 200 OK | HTTP/1.1 200 OK |
Intel | HTTP/1.1 200 OK | HTTP/1.0 400 Bad Request |
JetBrains | HTTP/1.1 301 Moved Permanently | HTTP/1.1 301 Moved Permanently |
KolibriOS Project Team | HTTP/1.1 404 Not Found | HTTP/1.1 301 Moved Permanently |
Mail.Ru Group | HTTP/1.1 200 OK | HTTP/1.1 200 OK |
Microsoft | HTTP/1.1 200 OK | HTTP/1.1 400 Bad Request |
Opera Software ASA | HTTP/1.1 404 Not Found | HTTP/1.1 400 BAD_REQUEST |
Rusonyx | HTTP/1.1 301 Moved Permanently | HTTP/1.1 301 Moved Permanently |
UIDG | HTTP/1.1 404 Not Found | HTTP/1.1 404 Not Found |
Zfort Group | HTTP/1.1 404 Not Found | HTTP/1.1 404 Not Found |
ВымпелКом (Билайн) | HTTP/1.1 302 Redirect | HTTP/1.1 400 Bad Request |
Мосигра | HTTP/1.1 301 Moved Permanently | HTTP/1.1 400 BAD_REQUEST |
Нордавинд | HTTP/1.1 200 OK | HTTP/1.1 200 OK |
Яндекс | HTTP/1.1 404 Not Found | HTTP/1.1 404 Not Found |
Запрос 16
Попробуем использовать произвольный домен.
Результаты совпали с предыдущим запросом.
Запрос 17
И в третий раз попробуем заменить домен на произвольный текст.
Уже ни одного положительного ответа от сервера. По сравнению с запросом 12 изменения есть у следующих сайтов:
Компания | Запрос 12 | Запрос 17 |
---|---|---|
Intel | HTTP/1.1 200 OK | HTTP/1.0 400 Bad Request |
KolibriOS Project Team | HTTP/1.1 400 Bad Request | HTTP/1.1 301 Moved Permanently |
Opera Software ASA | HTTP/1.1 200 OK | HTTP/1.1 400 BAD_REQUEST |
Мосигра | HTTP/1.1 404 Not Found | HTTP/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.