Проблема с правилами перезаписи utf-8 и правилами apache2
Я вижу сообщение о проверке utf-8 в правиле перезаписи htaccess, и я думаю, что это здорово, но у меня возникла более фундаментальная проблема:
Мне нужно было расширить, чтобы обрабатывать символы utf-8 для параметров строки запроса, имен каталогов, файлов и используемых в дисплеях для пользователей и т. Д.
Я настроил свой Apache с DefaultCharset utf-8, а также с моим php, если это имеет значение. Мое оригинальное правило перезаписи отфильтровывало все, кроме обычного A-Za-z, подчеркивания и дефиса. и это сработало. Что-нибудь еще даст вам 404 (это то, что я хочу!) Теперь, однако, кажется, что все совпадает, в том числе вещи, которые я не хочу, однако, хотя кажется, что это совпадает, не входит в строку запроса, если только обычная строка символов A-Za-z_-
Я нахожу это непонятным, потому что правило гласит: поместите в строку запроса все, что вам подходит:
Вот оригинальное правило:
RewriteRule ^/puzzle/([A-Za-z_-]+)$ /puzzle.php?g=$1 [NC]
и вот пересмотренное правило:
RewriteRule ^/puzzle/(\w+)$ /puzzle.php?g=$1 [NC]
Я сделал изменение, потому что где-то я прочитал, что \w соответствует ВСЕМ альфа-символам, где A-Zetc. только соответствует без акцентов и прочее.
Кажется, не имеет значения, какое из этих правил я использую: Вот что происходит:
В приложении у меня есть это:
echo $_GET['g'];
Если я передаю URL-адрес, например http://mydomain.com/puzzle/USA он повторяет "США" и работает нормально.
Если я передаю URL-адрес, например http://mydomain.com/puzzle/M%C3%A9xico, он ничего не говорит об этом и предупреждает, что индекс g не определен и, конечно, не получает ресурсы для Мексики.
если я передаю URL-адрес, например http://mydomain.com/puzzle/fuzzle/buzzle/j.qle он делает то же самое.
Этот последний случай должен быть 404!
И делает это независимо от того, какое из приведенных выше правил я использую. Я настроил переписать журнал
RewriteLogLevel 5
RewriteLog /opt/local/apache2/logs/puzzles.httpd.rewrite
но пусто
Вот из журнала обычного доступа (он дает статус 200)
[26/May/2010:11:21:42 -0700] "GET /puzzle/M%C3%A9xico HTTP/1.1" 200 342
[26/May/2010:11:21:54 -0700] "GET /puzzle/M/l.foo HTTP/1.1" 200 342
Что я могу сделать, чтобы получить эти $%#$@(*#@!!! символы, но не косую черту, точку или другой не-альфа в мою программу, и когда она там будет, она будет правильно их декодировать??? работать лучше? Есть ли что-то еще, что мне нужно настроить?
6 ответов
Я бы предложил вам активировать MultiViews и забыть mod_rewrite. Добавьте к вашей конфигурации apache в соответствующей Directory
/VirtualHost
раздел:
Options +MultiViews
#should already be set to this, but it doesn't hurt:
AcceptPathInfo Default
Нет, вы всегда можете опустить расширения, если клиент включает соответствующий тип MIME в своем заголовке Accept.
Теперь запрос на /puzzle/whatever
будет отображаться в /puzzle.php
а также $_SERVER['PATH_INFO']
будет заполнен /whatever
,
Если вы хотите сделать это с помощью mod_rewrite, это также возможно. Тестовая строка для RewriteRule
является неэкранированным (части%xx преобразуются в фактические байты, которые они представляют). Вы можете получить исходную экранированную строку, используя %{REQUEST_URI}
или же %{THE_REQUEST}
(последний также содержит HTTP-метод и версию).
По договоренности, веб-браузеры используют кодировку UTF-8 в URL. Это означает, что "Мексика" будет urlencoded M%C2%82xico
не M%82xico
, чего следовало ожидать, если бы браузеры использовали ISO-8859-1. Также, [a-zA-Z]
не будет соответствовать é
, Тем не менее, это должно работать:
RewriteCond %{REQUEST_URI} ^/puzzle/[^/]*$
RewriteRule ^/puzzle/(.*)$ /puzzle.php?q=$1 [B,L]
Тебе нужно B
чтобы избежать обратной ссылки, потому что вы используете ее в строке запроса, в которой набор разрешенных символов меньше, чем для остальной части URI.
То, что вы должны знать, это то, что RewriteRule
не поддерживает Unicode. Что-нибудь кроме .*
может дать (потенциально) неверные результаты. Четное [^/]
может не работать, потому что /
"Символ" (читай: байт) может быть частью многобайтовой последовательности символов. Если RewriteRule
были в курсе Unicode, ваше решение с \w
должно сработать.
Поскольку вы не хотите совпадать с подкаталогами, и RewriteRule ^/puzzle/[^/]*
не вариант, эта проверка откладывается до RewriteCond
который использует (сбежал) %{REQUEST_URI}
,
Это решение основано на: http://www.dracos.co.uk/code/apache-rewrite-problem/
Попробуйте переписать правила:
AddDefaultCharset UTF-8
RewriteEngine On
RewriteCond %{THE_REQUEST} /puzzle/([^?\ /]+)
RewriteRule ^puzzle/(.*)$ puzzle.php/%1 [L]
Как получить параметр запроса:
<?php
// Get query param
$g = substr($_SERVER['PATH_INFO'], 1);
echo "<p>g: $g</p>";
// Test if '/' is present in URL for 404's
$g2 = substr($_SERVER['REQUEST_URI'], 8);
if (strpos($g2, '/') === false) {
// do stuff
} else {
// Send 404 header here
echo "<p>404</p>";
}
?>
С этим решением вы должны отправить 404 от php.
Это ответ на ответ эсминца, но он слишком длинный.
Я перестал работать с URL, кодирующим Unicode, потому что его достаточно легко декодировать для отображения. Так что, возможно, это основная проблема. В конце концов, я просто использую url_encode в php, чтобы сделать это, но я подумал, что попробую подключиться к Интернету просто для проверки: я пошел на http://www.opinionatedgeek.com/dotnet/tools/urlencode/Encode.aspx и попытался закодировать Мехико и получилось M%c3%a9xico. Я пошел на сайт, который вы указали, и попробовал его, и он вышел M%E9xico другой!! Что он??? Думаю, мне придется принять все, что на самом деле даст мне функция php. Но у обоих из них есть 9, что означает, что я должен принимать цифры, а также%. Это ВСЕ, что я должен включить?
Я хотел бы надеяться, что запросы, запрашивающие подлинные подкаталоги, НЕ будут соответствовать этому правилу, если вы об этом подразумеваете, я бы предпочел, чтобы они фактически отображали статические страницы в подкаталогах. Вот почему я действительно хочу исключить / что я думал, что сделал. Но, похоже, соответствует чему-либо после / включая вложенные подкаталоги и попадания в файл puzzle.php.
Вот что я попробовал, но не радостно: я использовал это правило: RewriteRule ^/puzzle/([A-Za-z0-9_%-]+)$ /puzzle.php?g=$1 [NC], как вы видите, я добавил% и 0-9 к группе. Нужно ли бежать из% или что-то? Я читал, что только \ нужно выходить из квадратных скобок. Я надеюсь, что это то, что вы имеете в виду. Будут ли они единственным дополнительным символом, который вы получите, кодируя любую возможную строку юникода? Затем я передал 2 разные версии Мексики в кодировке URL. Для M%E9xico я теперь получаю 404 и это сообщение: Запрошенный URL /puzzle/México не найден на этом сервере. Для M% c3% a9xico я теперь получаю это сообщение на 404: Запрошенный URL /puzzle/México не был найден на этом сервере. А для несуществующих подкаталогов теперь выдается 404, как и должно быть. Так что теперь это просто правило перезаписи не работает. Это прогресс. Также журнал переписывания начал получать вещи в этом: Вот некоторые. Я буду гуглить за то, как читать эти журналы:
kidd108d-mac3:logs tpdick$ cat puzzles.httpd.rewrite
::1 - - [26/May/2010:15:54:37 --0700] [puzzles.net/sid#886b00][rid#904858/initial] (2) init rewrite engine with requested uri /puzzle/M?xico
::1 - - [26/May/2010:15:54:37 --0700] [puzzles.net/sid#886b00][rid#904858/initial] (3) applying pattern '^/puzzle/([A-Za-z0-9_%-]+)$' to uri '/puzzle/M?xico'
::1 - - [26/May/2010:15:54:37 --0700] [puzzles.net/sid#886b00][rid#904858/initial] (1) pass through /puzzle/M?xico
::1 - - [26/May/2010:15:54:37 --0700] [puzzles.net/sid#886b00][rid#910858/subreq] (3) [perdir /Users/tpdick/Sites/puzzles/] add path info postfix: /Users/tpdick/Sites/puzzles/puzzle.php -> /Users/tpdick/Sites/puzzles/puzzle.php/M?xico
::1 - - [26/May/2010:15:54:37 --0700] [puzzles.net/sid#886b00][rid#910858/subreq] (3) [perdir /Users/tpdick/Sites/puzzles/] strip per-dir prefix: /Users/tpdick/Sites/puzzles/puzzle.php/M?xico -> puzzle.php/M?xico
::1 - - [26/May/2010:15:54:37 --0700] [puzzles.net/sid#886b00][rid#910858/subreq] (3) [perdir /Users/tpdick/Sites/puzzles/] applying pattern '^(.*)/GeoP-Test/puzzle/(.*)$' to uri 'puzzle.php/M?xico'
::1 - - [26/May/2010:15:54:37 --0700] [puzzles.net/sid#886b00][rid#910858/subreq] (1) [perdir /Users/tpdick/Sites/puzzles/] pass through /Users/tpdick/Sites/puzzles/puzzle.php
::1 - - [26/May/2010:15:54:37 --0700] [puzzles.net/sid#886b00][rid#904858/initial] (3) [perdir /Users/tpdick/Sites/puzzles/] add path info postfix: /Users/tpdick/Sites/puzzles/puzzle.php -> /Users/tpdick/Sites/puzzles/puzzle.php/M?xico
::1 - - [26/May/2010:15:54:37 --0700] [puzzles.net/sid#886b00][rid#904858/initial] (3) [perdir /Users/tpdick/Sites/puzzles/] strip per-dir prefix: /Users/tpdick::1 - - [26/May/2010:15:54:37 --0700] [puzzles.net/sid#886b00][rid#904858/initial] (2) init rewrite engine with requested uri /puzzle/México
::1 - - [26/May/2010:15:54:37 --0700] [puzzles.net/sid#886b00][rid#904858/initial] (3) applying pattern '^/puzzle/([A-Za-z0-9_%-]+)$' to uri '/puzzle/México'
::1 - - [26/May/2010:15:54:37 --0700] [puzzles.net/sid#886b00][rid#904858/initial] (1) pass through /puzzle/México
::1 - - [26/May/2010:15:54:37 --0700] [puzzles.net/sid#886b00][rid#910858/subreq] (3) [perdir /Users/tpdick/Sites/puzzles/] add path info postfix: /Users/tpdick/Sites/puzzles/puzzle.php -> /Users/tpdick/Sites/puzzles/puzzle.php/México
::1 - - [26/May/2010:15:54:37 --0700] [puzzles.net/sid#886b00][rid#910858/subreq] (3) [perdir /Users/tpdick/Sites/puzzles/] strip per-dir prefix: /Users/tpdick/Sites/puzzles/puzzle.php/México -> puzzle.php/México
::1 - - [26/May/2010:15:54:37 --0700] [puzzles.net/sid#886b00][rid#910858/subreq] (3) [perdir /Users/tpdick/Sites/puzzles/] applying pattern '^(.*)/GeoP-Test/puzzle/(.*)$' to uri 'puzzle.php/México'
::1 - - [26/May/2010:15:54:37 --0700] [puzzles.net/sid#886b00][rid#910858/subreq] (1) [perdir /Users/tpdick/Sites/puzzles/] pass through /Users/tpdick/Sites/puzzles/puzzle.php
::1 - - [26/May/2010:15:54:37 --0700] [puzzles.net/sid#886b00][rid#904858/initial] (3) [perdir /Users/tpdick/Sites/puzzles/] add path info postfix: /Users/tpdick/Sites/puzzles/puzzle.php -> /Users/tpdick/Sites/puzzles/puzzle.php/México
Что теперь??
На...
RewriteRule ^ / puzzle / (\ w +) $ /puzzle.php?g=$1 [NC]
Кто-то исправит меня, если я ошибаюсь, но разве это не означает, что запросы на подкаталоги просто обходят это правило?
Кроме того, ленивый способ решить эту проблему - также сгруппировать по символу "%". Насколько я знаю, все, с чем вам разрешено работать - это любой URL-путь, это URL-кодирование. На самом деле, см.: http://www.blooberry.com/indexdot/html/topics/urlencoding.htm
Я уверен, что есть более продвинутые и лучшие способы сделать это, но это должно решить вашу непосредственную проблему.
Работать с CodeIgniter и utf-8 вьетнамским (Tiếng Việt) файлом.htaccess:
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.+[a-z,A-Z,0-9,ễ].+)$ index.php/$1 [L]
когда url имеет 'ễn', тогда error => RewriteRule имеет 'ễ'