
Недавно при тестировании одного веб-скрипта на Perl возникла такая проблема: при передаче данных методом GET с использованием mod_rewrite, из данных пропадали символы + и #.
Для примера, скрипт:
#!/usr/bin/perl
use CGI;
$cgi = CGI->new();
print $cgi->header();
print $cgi->param('param');
Вызываем http://localhost/cgi-bin/script.pl?param=C%2B%2B
В ответ, как и положено, увидим надпись C++.
Создаем файл .htaccess следующего содержания:
RewriteEngine On
RewriteRule ^param/(.*?)$ /cgi-bin/script.pl?param=$1
Вызываем http://localhost/param/C%2B%2B
И увидим только C.
Внимание, вопрос! Куда пропало %2B%2B и как с этим бороться?
Немного походив по сети, нашел человека с аналогичной проблемой.
Он писал, что проблема вызвана багом апача, из-за которого во время подстановки в mod_rewrite коды символов преобразуются в сами символы, а специфика форматов URL-адресов не позволяет передавать символы + и # в чистом виде.
Автор предложил выполнять подстановку не из самого правила, а из переменной %{THE_REQUEST}, в которой содержится запрос в исходной форме (что-то вроде «GET /category/C%2B%2B HTTP 1.1»).
Изменил .htaccess на такой:
RewriteEngine On
RewriteCond %{THE_REQUEST} ^GET[\ ]+/param/(.*?)[\ ]+HTTP.*$
RewriteRule ^param/(.*?)$ /cgi-bin/script.pl?param=%1
И всё заработало как положено!
Это, конечно, хорошо, но лишняя строка — не очень хорошо. Внимательно изучив описание флагов наткнулся на очень интересный флаг [B]:
Apache has to unescape URLs before mapping them, so backreferences will be unescaped at the time they are applied. Using the B flag, non-alphanumeric characters in backreferences will be escaped.
В конечном итоге мой .htaccess выглядит так:
RewriteEngine On
RewriteRule ^param/(.*?)$ /cgi-bin/script.pl?param=$1 [B]
И все работает как часы.
PS: Проверялось на apache 2.2.11.
Webmoney Z163628999150, R61715184597
|
28 Дек 2009
Ну, флаги в мод_реврайт это преважнейшая вещь — даже не знаю как ты умудрился без них обойтись с самого начала.