Проблема с правилами перезаписи 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 имеет 'ễ'

Другие вопросы по тегам