apache mod_rewrite: как добавить разные правила перезаписи для одного и того же каталога в зависимости от существования файла в другом каталоге?

В настоящее время у меня возникают проблемы с настройкой правил перезаписи в файле .htaccess для сервера Apache 2.2 с mod_rewrite. Вот общее представление о том, что я хочу сделать:

Допустим, домен сервера — example.com/, и все запросы к example.com/abc/ и пути ниже этого каталога должны быть перезаписаны. Есть два сценария:

  1. Запросы непосредственно к example.com/abc/ или example.com/abc/index.php должны стать запросами к example.com/index.php с дополнительным параметром, указывающим исходный каталог запроса. Приведу несколько примеров:

    • example.com/abc/ ==> example.com/abc/index.php?directory=abc
    • example.com/abc/?foo=1&bar=2 ==> example.com/abc/index.php?directory=abc&foo=1&bar=2
    • example.com/abc/?a=b&c=d ==> example.com/abc/index.php?directory=abc&a=b&c=d
    • ... и так далее
  2. Запросы к файлам в пределах example.com/abc/ должны стать запросами к файлам в example.com/, если эти файлы там существуют. параметр для указания текущего каталога. Приведу несколько примеров:

    • example.com/abc/image.png ==> example.com/image.png (if the later file exists)
    • example.com/abc/sub/file.css ==> example.com/sub/file.css (если существует более поздний файл)
    • example.com/abc/foo/bar/baz/name.js ==> example.com/foo/bar/baz/name.js (если существует более поздний файл)
    • ... и так далее.

Содержимое моего .htaccess в настоящее время выглядит примерно так:

RewriteEngine on
Options FollowSymLinks
RewriteBase /

# rule for files in abc/: map to files in root directory
RewriteCond $1 -f
RewriteRule ^abc/(.*?)$ $1

# rule for abc/index.php: map to index.php?directory=abc&...
RewriteCond $1 !-f
RewriteRule ^abc/(.*?)$ index.php?directory=abc&$1 [QSA]

Более позднее правило работает, запросы к example.com/abc/index.php переписываются как задумано. Однако это не работает для файлов в каталоге abc/. Любые подсказки о том, что я делаю неправильно здесь и как решить эту проблему, приветствуются. Какие изменения нужно внести в .htaccess, чтобы все заработало, как описано?


person Striezel    schedule 12.08.2016    source источник


Ответы (1)


Я нашел рабочее решение:

RewriteEngine on
Options FollowSymLinks
RewriteBase /

# rule for file in abc/: map them to files in document root
RewriteCond %{DOCUMENT_ROOT}/$1 -f
RewriteRule ^abc/(.*?)$ %{DOCUMENT_ROOT}/$1 [L]

# rule for abc/index.php: map to index.php?directory=abc&...
RewriteRule ^abc/(.*?)$ %{DOCUMENT_ROOT}/index.php?directory=abc&$1 [QSA,L]

Два основных отличия:

  • использование флага [L], чтобы указать, что никакие другие правила не должны рассматриваться после совпадения правила - вероятно, это было проблемой, почему казалось, что работает только последнее правило.
  • предваряя местоположения в условии и переписывая местоположение с помощью %{DOCUMENT_ROOT}, чтобы получить абсолютные пути.
person Striezel    schedule 13.08.2016