Перенаправить запросы, только если файл не найден?

Я надеюсь, что есть способ сделать это с помощью mod_rewrite и Apache, но, возможно, есть и другой способ.

На моем сайте я создал каталоги для обновленных версий сайта для клиентов. Если веб-корень /home/blah/www, каталог клиента будет /home/blah/www/clients/abc. Когда вы получаете доступ к каталогу клиента через веб-браузер, я хочу, чтобы он использовал любые запрошенные файлы в каталоге клиента, если они существуют. В противном случае я хочу, чтобы он использовал файл в корневом каталоге.

Например, допустим, клиенту не нужен собственный index.html. Поэтому какой-то код определит, что в /home/blah/www/clients/abc нет index.html, и вместо этого будет использовать тот, что в /home/blah/www. Имейте в виду, что я не хочу перенаправлять клиента в корневой каталог в любое время, я просто хочу использовать корневой веб-файл с таким именем, если в клиентском каталоге не указана его собственная копия. Веб-браузер по-прежнему должен указывать на /clients/abc независимо от того, существует ли файл там или в корне. Аналогичным образом, если есть запрос на news.html в клиентском каталоге и он действительно там существует, то просто отправьте этот файл вместо news.html корневого веб-узла. Опыт пользователя должен быть бесшовным.

Мне нужно, чтобы это работало для запросов на любое имя файла. Если мне нужно, например, добавить новую строку в .htaccess для каждого файла, который я, возможно, захочу перенаправить, это скорее сведет на нет цель, поскольку требуется слишком много обслуживания и велика вероятность ошибок, учитывая большое количество файлов.

В своих примерах укажите, находится ли ваш код в файле .htaccess в каталоге клиента или в корневом каталоге веб-сайта. Предпочтителен веб-корневой каталог.


person DivideByHero    schedule 27.02.2009    source источник


Ответы (6)


# If requested resource exists as a file or directory, skip next two rules
RewriteCond %{DOCUMENT_ROOT}/$1 -f [OR]
RewriteCond %{DOCUMENT_ROOT}/$1 -d
RewriteRule (.*) - [S=2]
#
# Requested resource does not exist, do rewrite if it exists in /archive
RewriteCond %{DOCUMENT_ROOT}/archive/$1 -f [OR]
RewriteCond %{DOCUMENT_ROOT}/archive/$1 -d
RewriteRule (.*) /archive/$1 [L]
#
# Else rewrite requests for non-existent resources to /index.php
RewriteRule (.*) /index.php?q=$1 [L] 

From Переписать, если файлы не существуют

person Jeremy L    schedule 27.02.2009

Как насчет этого?

# If requested resource exists as a file or directory go to it
RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule (.*) - [L]

# Else rewrite requests for non-existent resources to /index.php
RewriteRule (.*) /index.php?q=$1 [L]
person Happy    schedule 03.09.2012
comment
часть else была тем, чего я давно не знал... спасибо. - person T.Todua; 19.12.2018

Кажется, у меня была по крайней мере одна проблема с каждым из приведенных выше примеров. %{DOCUMENT_ROOT}, похоже, в некоторых местах работает неправильно, а некоторые символы /, похоже, отсутствуют. Вот мое решение, которое находится в папке .htaccess в корневом каталоге.

Вместо того, чтобы использовать два правила (одно для случая, когда файл в client/ найден, и одно для не найденного), все, что мне нужно проверить, это то, что запрошенный файл (или каталог) НЕ существует. Потому что, если он существует, никаких изменений не требуется, он может просто использовать файл, предоставленный в каталоге клиента. Вот код, на котором я остановился:

RewriteEngine on
RewriteCond %{DOCUMENT_ROOT}/clients/$1/$2 !-f
RewriteCond %{DOCUMENT_ROOT}/clients/$1/$2 !-d
RewriteRule ^clients/([^/]+)/(.*)$ $2 [L]

Спасибо за вашу помощь!

person DivideByHero    schedule 03.03.2009

Попробуй это:

RewriteEngine on
RewriteRule ^clients/abc/ - [L]
RewriteCond %{DOCUMENT_ROOT}clients/abc/$0 -f
RewriteRule .* clients/abc/$0 [L]
person Gumbo    schedule 27.02.2009
comment
Это предназначено для .htaccess в корневом каталоге? - person DivideByHero; 27.02.2009
comment
Да, он предназначен для файла .htaccess в корневом каталоге документа. - person Gumbo; 27.02.2009

Я думаю, вы хотите что-то в этом роде:

RewriteEngine on
RewriteCond %{DOCUMENT_ROOT}clients/$1/$2 -f
RewriteRule ^clients/([^/]+)/(.*)$ %{DOCUMENT_ROOT}clients/$1/$2 [L]
RewriteRule ^clients/([^/]+)/(.*)$ %{DOCUMENT_ROOT}$2 [L]
person jcrossley3    schedule 27.02.2009
comment
Хорошая точка зрения. Но в файлах .htaccess шаблон не должен начинаться с косой черты. И было бы удобнее, если бы вы использовали переменную DOCUMENT_ROOT. - person Gumbo; 27.02.2009
comment
Можете ли вы уточнить, как это должно быть обновлено с помощью DOCUMENT_ROOT? Это не работает как есть. - person DivideByHero; 27.02.2009
comment
Замените в RewriteCond «/home/blah/www/» на «%{DOCUMENT_ROOT}» и удалите его в подстановках. Также удалите начальный «/» в шаблонах регулярных выражений. Тогда это должно работать. - person Gumbo; 27.02.2009
comment
Я обновил в соответствии с вашими комментариями, Гамбо, спасибо. Я не рассматривал .htaccess - person jcrossley3; 27.02.2009

person    schedule
comment
Кажется слишком коротким, чтобы делать то, что я хочу. Можете немного объяснить логику? Спасибо! - person DivideByHero; 27.02.2009