Программное обеспечение моего веб-сайта заменяет пробелы в URL-адресе символами '+'. Правильная ссылка будет выглядеть так: 'http://www.schirmacher.de/display/INFO/How+to+reattach+a+disk+to+XenServer' например.
Некоторые веб-сайты ссылаются на эту статью, но каким-то образом их встроенный редактор не может обрабатывать кодировку, поэтому то, что я вижу в файлах журнала httpd, на самом деле
GET /display/INFO/How%2525252bto%2525252breattach%2525252ba%2525252bdisk%2525252bto%2525252bXenServer
что, конечно же, приводит к ошибке 404. Кажется, что символ «+» кодируется как «% 2b», а затем символ «%» кодируется как «% 25» - несколько раз.
Поскольку существует много таких ссылок на разные страницы с разных веб-сайтов, я хотел бы переписать URL-адрес, чтобы посетители получали правильную страницу.
Вот моя попытка, которая не работает:
RewriteRule ^(.*)%25(.*)$ $1%$2 [R=301]
Предполагается, что он должен: взять все, что находится перед строкой% 25 и все после нее, объединить эти строки с «%» между ними, а затем выполнить перенаправление.
В примере входного URL-адреса правило следует переписать на
/display/INFO/How%25252bto%2525252breattach%2525252ba%2525252bdisk%2525252bto%2525252bXenServer
с последующим перенаправлением, затем его следует переписать на
/display/INFO/How%252bto%2525252breattach%2525252ba%2525252bdisk%2525252bto%2525252bXenServer
и снова к
/display/INFO/How%2bto%2525252breattach%2525252ba%2525252bdisk%2525252bto%2525252bXenServer
и так далее. Наконец, после множества перенаправлений я должен был уйти
/display/INFO/How%2bto%2breattach%2ba%2bdisk%2bto%2bXenServer
который является действительным URL-адресом, эквивалентным / display / INFO / How + to + reattach + a + disk + to + XenServer.
Моя проблема в том, что выражение вообще не соответствует, поэтому оно даже не заменяет ни единого вхождения% 25.
Я понимаю, что существует ограничение на количество перенаправлений, и мне действительно следует использовать флаг [N], однако я даже не могу правильно сделать первый шаг.
@ Бен Ли: спасибо за подробный ответ. Я потратил несколько часов на эту проблему. Вот что я выяснил:
Любая строка «% 25» в URL-адресе преобразуется в «%» до того, как mod_rewrite ее увидит. Итак, RewriteRule ^ (.)% 25 (.) $ не соответствует "% 25" в URL-адресе, фактически соответствует "% 2525".
Наличие обратной косой черты не имеет значения. Похоже, что знак «%» в моем случае не интерпретируется как обратная ссылка, возможно потому, что раньше не было инструкции RewriteCond. Но, наверное, лучше использовать, на всякий случай.
Строка с [L, R = 301] неверна. Он будет пытаться перенаправить для каждого совпадения% 2b, но есть предел разрешенных перенаправлений, и он не удастся, если их будет больше.
Вот строки mod_rewrite, которые я использую:
RewriteRule ^(.*)\%25(.*\%25.*)$ $1%$2 [N]
RewriteRule ^(.*)\%25(.*)$ $1%$2 [R=301,L]
RewriteRule ^(.*)\%2b(.*\%2b.*)$ $1+$2 [N]
RewriteRule ^(.*)\%2b(.*)$ $1+$2 [R=301,L]
Третья строка заменит все последовательности% 2b, кроме одной, на символ "+". Когда осталась только одна последовательность% 2b, четвертая строка будет соответствовать, вызывая перенаправление.
Первая и вторая строки в основном одинаковы, но с последовательностью% 25. Необходимо иметь правило с флагом [R] для каждой возможной последовательности символов, потому что я также использую mod_proxy / mod_jk, и перенаправление будет гарантировать, что результирующий URL-адрес снова будет передан каждому модулю. В противном случае httpd попытается получить URL-адрес с диска, что в моем случае не удастся.
Вот ваше первоначальное правило с [L]
добавлено для обозначения «последнего»:
RewriteRule ^(.*)%25(.*)$ $1%$2 [L,R=301]
После этого здесь возникает несколько проблем. Во-первых, знаки процента RewriteRule
узоры имеют особое значение; они обозначают начало обратной ссылки на RewriteCond
. Вы можете обойти это, экранируя их (используя обратную косую черту):
RewriteRule ^(.*)\%25(.*)$ $1%$2 [L,R=301]
Во-вторых, когда вы вставляете %
в замене, он не будет рассматривать это как часть части, закодированной в uri. Это переводится как буквальный знак процента. В исходном URL-адресе, который вы получаете, первый %25"
также преобразуется в буквальный знак процента. Таким образом, приведенное выше правило приведет к буквальному %25
s или буквальный %2b
в URL-адресе вместо разрешения %
или +
. Поэтому вам нужно вручную решить их самостоятельно.
RewriteRule ^(.*)\%25(.*)$ $1%$2
RewriteRule ^(.*)\%2b(.*)$ $1+$2 [L,R=301]
Наконец, поскольку у вас нет ни одного 25
после начального %
, но потенциально многие используют [N]
для обозначения «следующий». Это в основном означает «начать процесс с самого начала, но использовать мой новый URL в качестве ввода». Так что это будет иметь дело с любым количеством 25
s после процента:
RewriteRule ^(.*)\%25(.*)$ $1%$2 [N]
RewriteRule ^(.*)\%2b(.*)$ $1+$2 [L,R=301]
Примечание. Это должно работать, если вы настраиваете свое правило в обычных конфигурациях apache. Если вы настраиваете его как .htaccess
, ведущие косые черты исключаются из строки, проверяемой регулярным выражением, и в этом случае вам придется добавить их обратно в себя:
RewriteRule ^(.*)\%25(.*)$ /$1%$2 [N]
RewriteRule ^(.*)\%2b(.*)$ /$1+$2 [L,R=301]
ОБНОВИТЬ: Сейчас у меня нет возможности протестировать, но, просмотрев документацию, я увидел вариант NE
для "выхода без выхода", заставляющего проц в результате работать как обычные маркеры кодирования. Если я правильно понял, это означает, что правило можно упростить до следующего:
RewriteRule ^(.*)\%25(.*)$ $1%$2 [NE,N,L,R=301]
Но опять же, это не проверено, и я никогда не использовал NE
flag, поэтому я могу неправильно это понять. Если вы протестируете это и обнаружите, что он работает, дайте мне знать, и я удалю это ОБНОВЛЕНИЕ и просто исправлю приведенный выше ответ, чтобы включить эту более простую версию.