проблема с правилами перезаписи utf-8 и правилами переписывания apache2 - PullRequest
11 голосов
/ 26 мая 2010

Я вижу сообщение , проверяющее 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, он повторяет "USA" и работает нормально.
Если я передаю ему URL-адрес типа http://mydomain.com/puzzle/México, он ничего не говорит об этом и предупреждает, что индекс 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

Что я могу сделать, чтобы получить эти символы $% # $ @ (* # @ !!!, но не косую черту, точку или другой не-альфа в мою программу, и когда она там будет, она будет правильно их декодировать ??? Классы posix char работают лучше? Мне нужно что-то еще настроить?

Ответы [ 6 ]

1 голос
/ 29 мая 2010

Это решение основано на: 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.

1 голос
/ 29 мая 2010

Я бы посоветовал вам активировать 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, который использует (экранированный) %{REQUEST_URI}.

1 голос
/ 27 мая 2010

Это ответ на ответ эсминца, но он слишком длинный.

Я заболел URL, кодирующим юникод, потому что его достаточно легко декодировать для отображения. Так что, возможно, это основная проблема. В конце концов, я просто использую 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 разные версии Мексики в кодировке URL. Для M% E9xico я теперь получаю 404 и это сообщение: Запрашиваемый URL / пазл / 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

Что теперь?

1 голос
/ 27 мая 2010

On ...

RewriteRule ^/puzzle/(\w+)$ /puzzle.php?g=$1 [NC]

Кто-то поправит меня, если я ошибаюсь, но разве это не означает, что запросы на подкаталоги просто обходят это правило?

Кроме того, ленивый способ решить эту проблему также состоит в группировке по символу «%». Насколько я знаю, все, с чем вам разрешено работать, это любой URL-путь, это URL-кодирование. На самом деле, см .: http://www.blooberry.com/indexdot/html/topics/urlencoding.htm

Я уверен, что есть более продвинутые и лучшие способы сделать это, но это должно решить вашу непосредственную проблему.

0 голосов
/ 20 ноября 2017

проверить это ([^/]+) это может работать для вас

0 голосов
/ 11 августа 2017

работа с 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 имеет 'ễ'

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...