Назад | Перейти на главную страницу

Apache RewriteMap с URL-адресами, содержащими пробел, не работает

Я на самом деле использую RewriteMap директива внутри моего виртуального хоста для перенаправления списка из 800 URL-адресов. Работает тихо хорошо:

RewriteEngine On
RewriteMap redirects dbm=db:/data/apps/project/current/configuration/etc/httpd/conf/redirects.db
RewriteCond ${redirects:$1} !=""
RewriteRule ^(.*)$ ${redirects:$1} [redirect=permanent,last]

Я использую redirect.txt файл, содержащий отображение. Затем он преобразуется в файл db:

httxt2dbm -f db -i /data/apps/project/current/configuration/etc/httpd/conf/redirects.txt -o /data/apps/project/current/configuration/etc/httpd/conf/redirects.db

Например, для такого типа URL это нормально:

/associations/old_index.php /

Но когда URL-адрес содержит пробелы, он не работает: (я полагаю, это будет то же самое с другими специальными символами)

/Universités%20direct   /

Как поступить в этом случае?

Вы можете использовать вторую карту перезаписи, внутренняя функция escape превращает пробелы в% 20:

RewriteMap ec int:escape

RewriteMap redirects dbm=db:/data/apps/project/current/configuration/etc/httpd/conf/redirects.db

RewriteCond ${redirects:${ec:$1}} !=""

RewriteRule ^(.*)$ ${redirects:${ec:$1}} [redirect=permanent,last]

Затем в вашей собственной карте перезаписи db вы можете иметь:

/Universités-direct%20/

Тогда это должно совпадать.

Вы можете решить эту проблему, извлекая закодированный URI из переменной% {THE_REQUEST} и используя его для поиска. Конечно, вам нужно поместить закодированные URI на карту. Примерно так:

RewriteEngine On
RewriteMap redirects dbm=db:/data/apps/project/current/configuration/etc/httpd/conf/redirects.db
RewriteCond %{THE_REQUEST} "\w+ ([^ ]+)"
RewriteRule ^ - [E=MYVAR:%1]

RewriteCond ${redirects:%{ENV:MYVAR}} !=""
RewriteRule ^ ${redirects:%{ENV:MYVAR}} [redirect=permanent,last] [B]

Я тестировал его только с текстовой картой, а не с базой данных. Это, вероятно, потребует модификации, если вам придется иметь дело с URL-адресами со строками запроса.

Обходной путь может заключаться во внутренней перезаписи URL-адресов, содержащих пространство на дефис (замените пробел на дефис) и вместо этого включите URL-адрес с переносом в вашу карту перезаписи.

Если у вас есть только некоторые URL-адреса, которые содержат один пробел в URL-адресе, вы можете использовать что-то вроде следующей директивы перед существующими директивами:

RewriteRule ^(.+)\s(.+)$ $1-$2

А затем используйте в своей карте перезаписи следующее:

/Universités-direct /

ОБНОВИТЬ: Если у вас есть URL-адреса, содержащие два пробела (например, /the force awakens) и некоторые с одним пробелом, вы можете добавить дополнительное правило:

RewriteRule ^(.+)\s(.+)\s(.+)$ $1-$2
RewriteRule ^(.+)\s(.+)$ $1-$2

Эти правила предполагают, что у вас нет URL-адресов, заканчивающихся пробелом. И ни один URL не содержит более одного непрерывного пробела.

Если три пробела, добавьте еще одно правило перед указанным выше ...

RewriteRule ^(.+)\s(.+)\s(.+)\s(.+)$ $1-$2

Я бы предпочел сделать это с несколькими (простыми) правилами, а не с общим правилом «преобразовать все в одно правило», если вам это специально не нужно. Общее правило будет выполняться рекурсивно, сокращая несколько пробелов до одного символа. Вам также, вероятно, потребуются дополнительные флаги (т.е. DPI), чтобы предотвратить известную ошибку перезаписи в Apache.