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

mod_rewrite, чистые URL-адреса и каталоги содержимого страницы

Я использую mod_rewrite в файле .htaccess в нашем корневом веб-каталоге, чтобы мы могли использовать более чистые URL-адреса для некоторых конкретных случаев. Например, мы хотим перевести:

http://example.com/Topic/ABCD/Type/Description

в

http://example.com/Topic.php?l=ABCD&e=Type&t=Description

Это казалось достаточно простым; файл .htaccess состоит из:

RewriteEngine on
RewriteRule ^Topic/([^/\.]+)/([^/\.]+)/([^/\.]+)/?$ /Topic.php?l=$1&e=$2&t=$3 [L]

Однако все содержимое страницы (файлы .CSS, изображения и т. Д.) Заканчивается 404, потому что вместо, скажем, загрузки "/Common.css" из каталога относительно перезаписанного URL:

http://example.com/Common.css

он загружает его из каталога непереписанного URL:

http://example.com/Topic/ABCD/Type/Description/Common.css

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

Я пробовал добавлять правила ранее в файл .htaccess, чтобы попытаться сократить запросы контента, например:

RewriteRule \.(css|jpe?g|gif|png)$ - [L]

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

Если я изменю правило так, что его флаг установлен на перенаправление ([R, L] вместо просто [L]), тогда все будет работать нормально - за исключением того, что теперь браузер отображает переписанную строку параметра php, что и было пытаюсь избежать. Раньше мы просто принимали это как обходной путь, но теперь я пытаюсь понять, почему это так работает, и что я могу с этим поделать.

Если это актуально, я использую CentOS 6.2 и Apache / 2.2.15.

Проблема, скорее всего, в том, что ваш код генерирует страницы, содержащие CSS, например:

<link rel="stylesheet" type="text/css" href="Common.css" />

Поскольку браузер видит это и видит полученный URL-адрес как подпуть, он делает запрос Common.css по этому подпутью.

Вы могли бы (но не должны, по причинам, которые я объясню позже) создать еще несколько правил перезаписи, которые перезаписывают Common.css и т.д. в один на верхнем уровне, например:

RewriteEngine на
RewriteRule ^ Topic /([^/.pting+)/([^/.pting+)/([^/.pting+)/ Common.css $ /Common.css [L]

ОДНАКО, это было бы глупо, поскольку весь смысл CSS заключается в том, чтобы разрешить кеширование и т. Д. Гораздо лучший подход - просто добавить / перед Common.css в вашем коде, чтобы он создавал CSS следующим образом:

<link rel="stylesheet" type="text/css" href="/Common.css" />

Таким образом, все страницы используют один и тот же файл Common.css, и браузеру не нужно извлекать копию одного и того же файла в нескольких логических местах на каждой странице, и, более того, браузер знает, как получить ее на верхнем уровне. , а не на подстранице.

PS Якуб: регулярное выражение для RewriteRule уже исключает все, что имеет точку, которая уже охватывает .css, .jpg и т.д., поэтому добавление дополнительного RewriteCond не поможет.

Ответ относительно прост - вы должны использовать базовый href в своем html-коде, потому что процесс перезаписи URI сбрасывает базовый URL-адрес, который вызывает 404-е, которые вы испытывали.

Об этом есть хорошая статья на http://pixelcode.co.uk/tutorials/Clean+URLs+with+mod_rewrite.html

С уважением, Майлз

Вы должны использовать RewriteCond

RewriteEngine on
RewriteCond $1 !^(\.css|\.js|\.png|\.jpg)
RewriteRule ^Topic/([^/\.]+)/([^/\.]+)/([^/\.]+)/?$ /Topic.php?l=$1&e=$2&t=$3 [L]