Apache: как дважды декодировать входящие URL-адреса с двойным кодированием

У меня проблема с моим приложением Rails, работающим под Passenger/Apache, где робот Googlebot пытается получить доступ к URL-адресам, где параметры строки запроса были закодированы дважды. (Я понятия не имею, откуда робот Googlebot получает эти URL-адреса — их нет ни в каких ссылках в моем приложении.)

Это приводит к большому количеству дополнительных ошибок в моих журналах, что очень затрудняет диагностику «настоящих» проблем, поскольку они скрыты под ошибками, вызванными URL-адресами, к которым Googlebot пытается получить доступ.

Вот пример из моих журналов доступа к Apache:

66.249.67.103 - - [27/окт/2014:07:44:32 -0400] "GET /catalog?f%255Bfacet_field_1%255D%255B%255D=foo&f%255Bfacet_field_2%255D%255B%255D=bar&sort=title_info_primary_ssort+asc %252C+date_start_dtsi+asc HTTP/1.1" 200 5266 "-" "Mozilla/5.0 (совместимый; Googlebot/2.1; +http://www.google.com/bot.html)"

Обратите внимание на двойное кодирование ("%255B", "%255D"), которое представляет собой закодированную версию уже закодированных символов ("%5B", "%5D"). Итак, вместо того, чтобы мое приложение Rails получало эти параметры:

{
  "f[facet_field_1][]" => "foo",
  "f[facet_field_2][]" => "bar",
  "sort" => "title_info_primary_ssort asc, date_start_dtsi asc"
}

... он получает это:

{
  "f%5Bfacet_field_1%5D%5B%5D" => "foo",
  "f%5Bfacet_field_2%5D%5B%5D" => "bar",
  "sort"=>"title_info_primary_ssort asc%2C date_start_dtsi asc"
}

... который он не может интерпретировать, что приводит к большому количеству записей в журналах ошибок. URL-адрес декодируется один раз (почти уверен, что Apache делает это по умолчанию), но это по-прежнему оставляет закодированные URL-адреса символы в хэше параметров, с которыми Rails не может справиться.

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

Как я могу указать Apache дважды декодировать URL-адрес (на основе пользовательского агента), прежде чем он передаст запрос моему приложению? (Версия сервера: Apache/2.4.7 (Ubuntu)). Блокировка робота Googlebot неприемлема.


person eben.english    schedule 29.10.2014    source источник


Ответы (1)


Есть способ сделать это, но он требует модификации файла .conf сервера. Вам необходимо добавить в конфигурацию сервера следующую директиву:

RewriteMap unescape int:unescape

После этого вы можете использовать RewriteRule примерно так:

RewriteEngine On
RewriteCond %{IS_SUBREQ} false
RewriteRule ^(.*)$ $1?${unescape:%{QUERY_STRING}} [L]

И, как я думаю, это нужно делать не для каждого запроса, а только для тех, которые нужно расшифровать, поэтому требуется дополнительный RewriteCond. Можно проверить, например, наличие %255B, %255D и так далее.

Итак, окончательный набор правил будет (может срабатывать при наличии символов в двойных кавычках в значениях элементов, а не только в именах параметров)

RewriteEngine On
RewriteCond %{IS_SUBREQ} false
RewriteCond %{QUERY_STRING} %255(B|D)
RewriteRule ^(.*)$ $1?${unescape:%{QUERY_STRING}} [L]
person Cheery    schedule 29.10.2014
comment
Это хорошо работает - спасибо! FWIW, я решил вернуть ответ 400 Bad Request на эти запросы Googlebot вместо того, чтобы перенаправлять их, как если бы параметры были правильно закодированы: «RewriteCond %{HTTP_USER_AGENT} Googlebot RewriteCond %{QUERY_STRING} %25[25][BC] Правило перезаписи. - [R=400,L]' - person eben.english; 31.10.2014