Проблема с utf-8 chars & apache2 переписать правила
Я вижу post проверку utf-8 в правиле перезаписи htaccess, и я думаю, что это здорово, но более фундаментальная проблема, с которой я столкнулся в первую очередь:
Мне нужно было расширить, чтобы обрабатывать символы utf-8 для параметров строки запроса, имена каталогов, файлов и использоваться в дисплеях для пользователей и т.д.
Я настроил свой Apache с помощью utf-8 DefaultCharset, а также мой 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/Mexico, он ничего не говорит об этом и предупреждает меня, что индекс 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
Что я могу сделать, чтобы получить эти $% # [email protected](* # @!!! символы, но не косую черту, точку или другую не-альфу в мою программу, и как только там, будет ли она правильно декодировать их? posix char работают лучше? Есть ли что-то еще, что мне нужно настроить?
Ответы
Ответ 1
Вкл...
RewriteRule ^/puzzle/(\w+)$ /puzzle.php?g=$1 [NC]
Кто-то исправит меня, если я ошибаюсь, но разве это не означает, что запросы, запрашивающие подкаталоги, просто обходят это правило?
Кроме того, ленивый способ решить эту проблему - также группировать символ "%". Насколько я знаю, все, с чем вам разрешено работать, находится на любом URL-адресе, это кодировка url. Фактически, см. http://www.blooberry.com/indexdot/html/topics/urlencoding.htm
Я уверен, что есть более продвинутые и лучшие способы сделать это, но это должно решить вашу непосредственную проблему.
Ответ 2
Это ответ на ответ эсминца, но он слишком длинный.
Я с кодировкой URL-адреса unicode, потому что это достаточно просто, чтобы расшифровать его для отображения. Так что, может быть, основная проблема. В конце концов, я просто использую url_encode в php для этого, но я подумал, что попробую онлайн-тест, чтобы проверить вещи: я пошел в http://www.opinionatedgeek.com/dotnet/tools/urlencode/Encode.aspx и попытался закодировать México и вышел M% c3% a9xico. Я пошел на сайт, который вы указали, и попробовал его, и он вышел на M% E9xico. Что он??? Думаю, мне пришлось бы принять то, что фактически предоставила мне функция php. Но у обоих из них есть 9, что означает, что я должен принимать цифры, а также%. Это ВСЕ, что мне нужно включить?
Я надеюсь, что запросы, запрашивающие подлинные подкаталоги, не будут соответствовать этому правилу, если это то, что вы подразумеваете, обходя его, я бы предпочел, чтобы они отображали статические страницы в подкаталогах. Вот почему я действительно хочу исключить/что я думал, что сделал. Но, похоже, что-то похоже на то, что после/включая вложенные подкаталоги и переход в файл puzzle.php.
Вот что я пробовал, но без радости: я использовал это правило: RewriteRule ^/puzzle/([A-Za-z0-9 _% -] +) $/puzzle.php?g=$1 [NC]
как вы видите, я добавил группу% и 0-9 в группу. Нужно ли мне избегать% или что-то еще? Я читал, что только\требуется экранирование внутри квадратных скобок. Я надеюсь, что ты имеешь в виду. Будет ли это единственным дополнительным символом, который вы получите, кодируя любую возможную строку юникода? затем я передал 2 разных кодированных в Мексике версии Мексики. Для M% E9xico теперь я получаю 404, и это сообщение:
Запрошенный URL/puzzle/México не найден на этом сервере. Для M% c3% a9xico теперь я получаю это сообщение на 404: запрошенный URL/puzzle/MÃ © xico не найден на этом сервере. А для несуществующих подкаталогов теперь дается 404, как и должно быть. Итак, теперь это не правило перезаписи. Этот прогресс. Также журнал перезаписи начал получать материал в нем: вот некоторые из них. Я буду google для того, чтобы прочитать эти журналы:
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
Теперь что??
Ответ 3
Я предлагаю вам активировать 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-адресах. Это означает, что "México" будет привязан к 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
, которая использует (escaped) %{REQUEST_URI}
.
Ответ 4
Это решение основано на: 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.
Ответ 5
работать с CodeIgniter и utf-8 vietnamese (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", тогда ошибка = > RewriteRule имеет "ễ"
Ответ 6
проверить его ([^/]+)
он может сработать для вас