Я написал веб-приложение, которое я запускаю на выделенном сервере для размещения веб-приложения. Экземпляры этого веб-приложения доступны в разных доменах, и каждый домен имеет свою собственную копию файлов веб-приложения, что позволяет при необходимости настраивать его.
Я запускаю Apache / 2.2.16 под Debian Squeeze.
I выполнять всю настройку в соответствии с директивой VirtualHost и не использовать файлы .htaccess.
Чтобы упростить конфигурацию apache, я хочу сохранить одну директиву Directory, например:
<Directory "/srv/www/*/public/">
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} !=/favicon.ico
RewriteCond %{REQUEST_URI} !=/robots.txt
RewriteRule ^(.+)$ /index.php?q=$1 [L,QSA]
</Directory>
Однако RewriteRule дает неправильные результаты, потому что при использовании подстановочного символа Directory префикс для каталога не удаляется.Вот результат журнала перезаписи:
[rid#b9832078/initial] (3) [perdir /srv/www/*/public/] applying pattern '^(.+)$' to uri '/srv/www/domain1/public/login'
[rid#b9832078/initial] (4) [perdir /srv/www/*/public/] RewriteCond: input='/srv/www/domain1/public/login' pattern='!-f' => matched
[rid#b9832078/initial] (4) [perdir /srv/www/*/public/] RewriteCond: input='/srv/www/domain1/public/login' pattern='!-d' => matched
[rid#b9832078/initial] (4) [perdir /srv/www/*/public/] RewriteCond: input='/login' pattern='!=/favicon.ico' => matched
[rid#b9832078/initial] (4) [perdir /srv/www/*/public/] RewriteCond: input='/login' pattern='!=/robots.txt' => matched
[rid#b9832078/initial] (2) [perdir /srv/www/*/public/] rewrite '/srv/www/domain1/public/login' -> '/index.php?q=/srv/www/domain1/public/login'
[rid#b9832078/initial] (3) split uri=/index.php?q=/srv/www/domain1/public/login -> uri=/index.php, args=q=/srv/www/domain1/public/login
[rid#b9832078/initial] (1) [perdir /srv/www/*/public/] internal redirect with /index.php [INTERNAL REDIRECT]
[rid#b9847440/initial/redir#1] (3) [perdir /srv/www/*/public/] applying pattern '^(.+)$' to uri '/srv/www/domain1/public/index.php'
[rid#b9847440/initial/redir#1] (4) [perdir /srv/www/*/public/] RewriteCond: input='/srv/www/domain1/public/index.php' pattern='!-f' => not-matched
[rid#b9847440/initial/redir#1] (1) [perdir /srv/www/*/public/] pass through /srv/www/domain1/public/index.php
Проблема в том, что RewriteRule 'uri' - это путь к файловой системе, а не путь URL-адреса, что приводит к неверной строке запроса: q = / srv / www / domain1 / public / login
Явное указание пути к каталогу, например:
<Directory "/srv/www/domain1/public/">
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} !=/favicon.ico
RewriteCond %{REQUEST_URI} !=/robots.txt
RewriteRule ^(.+)$ /index.php?q=$1 [L,QSA]
</Directory>
Работает нормально, и вот результат журнала перезаписи, показывающий правильное поведение (разница в том, что новая первая дополнительная строка предоставляет правильный ввод для остальная часть переписывания приводит к правильной строке запроса: q = login ):
[rid#b9868048/initial] (3) [perdir /srv/www/domain1/public/] strip per-dir prefix: /srv/www/domain1/public/login -> login
[rid#b9868048/initial] (3) [perdir /srv/www/domain1/public/] applying pattern '^(.+)$' to uri 'login'
[rid#b9868048/initial] (4) [perdir /srv/www/domain1/public/] RewriteCond: input='/srv/www/domain1/public/login' pattern='!-f' => matched
[rid#b9868048/initial] (4) [perdir /srv/www/domain1/public/] RewriteCond: input='/srv/www/domain1/public/login' pattern='!-d' => matched
[rid#b9868048/initial] (4) [perdir /srv/www/domain1/public/] RewriteCond: input='/login' pattern='!=/favicon.ico' => matched
[rid#b9868048/initial] (4) [perdir /srv/www/domain1/public/] RewriteCond: input='/login' pattern='!=/robots.txt' => matched
[rid#b9868048/initial] (2) [perdir /srv/www/domain1/public/] rewrite 'login' -> '/index.php?q=login'
[rid#b9868048/initial] (3) split uri=/index.php?q=login -> uri=/index.php, args=q=login
[rid#b9868048/initial] (1) [perdir /srv/www/domain1/public/] internal redirect with /index.php [INTERNAL REDIRECT]
[rid#b987d5f8/initial/redir#1] (3) [perdir /srv/www/domain1/public/] strip per-dir prefix: /srv/www/domain1/public/index.php -> index.php
[rid#b987d5f8/initial/redir#1] (3) [perdir /srv/www/domain1/public/] applying pattern '^(.+)$' to uri 'index.php'
[rid#b987d5f8/initial/redir#1] (4) [perdir /srv/www/domain1/public/] RewriteCond: input='/srv/www/domain1/public/index.php' pattern='!-f' => not-matched
[rid#b987d5f8/initial/redir#1] (1) [perdir /srv/www/domain1/public/] pass through /srv/www/domain1/public/index.php
Я ожидаю, что столкнулся с ошибкой с Apache, но если это не так, что я делаете что-то не так?
Хотя я ценю вклад в изменение подхода к другому работоспособному решению, я бы принял ответ, который решает эту проблему в рамках принятого мной подхода (например, без использования .htaccess), если только не будет продемонстрировано, что этот подход является не разрешима.
Так есть ли что-то, что нужно изменить в RewriteCond / Rules при использовании в Каталоге с подстановочными знаками? [12 271] Боковое примечание для любопытных: для дальнейшего упрощения я использую один VirtualHost с VirtualDocumentRoot - однако это не связано, поскольку эта проблема воспроизводится с использованием DocumentRoot и тестированием в одном домене.
EDIT
Хорошо, я Мы еще раз рассмотрели это, основываясь на ответе regilero , и вот что происходит - перемещение Rewrite, как есть, из каталога приводит к небольшой начальной проблеме, связанной с изменением строки запроса с "login" на " / login ", это исправлено изменением RewriteRule на: RewriteRule ^ / (. +) $ /index.php?q=$1 [L, QSA]
, который исправляет мой предыдущий комментарий" необъяснимо не работает ". .
После этого все статические файлы не загружаются, вот журнал перезаписи, показывающий эту проблему:
[rid#b7bc7fa0/initial] (2) init rewrite engine with requested uri /login
[rid#b7bc7fa0/initial] (3) applying pattern '^/(.+)$' to uri '/login'
[rid#b7bc7fa0/initial] (4) RewriteCond: input='/login' pattern='!-f' => matched
[rid#b7bc7fa0/initial] (4) RewriteCond: input='/login' pattern='!-d' => matched
[rid#b7bc7fa0/initial] (4) RewriteCond: input='/login' pattern='!=/favicon.ico' => matched
[rid#b7bc7fa0/initial] (4) RewriteCond: input='/login' pattern='!=/robots.txt' => matched
[rid#b7bc7fa0/initial] (2) rewrite '/login' -> '/index.php?q=login'
[rid#b7bc7fa0/initial] (3) split uri=/index.php?q=login -> uri=/index.php, args=q=login
[rid#b7bc7fa0/initial] (2) local path result: /index.php
[rid#b7bc7fa0/initial] (2) prefixed with document_root to /srv/www/domain1/public/index.php
[rid#b7bc7fa0/initial] (1) go-ahead with /srv/www/domain1/public/index.php [OK]
[rid#b7be6b80/initial] (2) init rewrite engine with requested uri /static/css/common.css
[rid#b7be6b80/initial] (3) applying pattern '^/(.+)$' to uri '/static/css/common.css'
[rid#b7be6b80/initial] (4) RewriteCond: input='/static/css/common.css' pattern='!-f' => matched
[rid#b7be6b80/initial] (4) RewriteCond: input='/static/css/common.css' pattern='!-d' => matched
[rid#b7be6b80/initial] (4) RewriteCond: input='/static/css/common.css' pattern='!=/favicon.ico' => matched
[rid#b7be6b80/initial] (4) RewriteCond: input='/static/css/common.css' pattern='!=/robots.txt' => matched
[rid#b7be6b80/initial] (2) rewrite '/static/css/common.css' -> '/index.php?q=static/css/common.css'
[rid#b7be6b80/initial] (3) split uri=/index.php?q=static/css/common.css -> uri=/index.php, args=q=static/css/common.css
[rid#b7be6b80/initial] (2) local path result: /index.php
[rid#b7be6b80/initial] (2) prefixed with document_root to /srv/www/domain1/public/index.php
[rid#b7be6b80/initial] (1) go-ahead with /srv/www/domain1/public/index.php [OK]
Но, как я сказал в своем комментарии к ответу regilero , это решается с помощью префикса директивы RewriteCond TestString с% {DOCUMENT_ROOT}. Однако использование% {DOCUMENT_ROOT} не работает при использовании VirtualDocumentRoot.
Мне кажется неправильным, что префикс% {DOCUMENT_ROOT} должен быть необходим.
EDIT
REQUEST_FILENAME
Полная локальная файловая система путь к файлу или скрипту, соответствующему запрос, если это уже было определено сервером в то время Ссылка на REQUEST_FILENAME. В противном случае, например, при использовании в контекст виртуального хоста, то же значение, что и REQUEST_URI.
, что объясняет необходимость префикса DOCUMENT_ROOT.
Я обновил правила перезаписи следующим образом:
RewriteCond %{REQUEST_URI} !=/favicon.ico
RewriteCond %{REQUEST_URI} !=/robots.txt
RewriteCond %{REQUEST_URI} !^/static/
RewriteRule ^/(.+)$ /index.php?q=$1 [PT,L,QSA]
Что работает нормально (Примечание: флаг PT необходим для избегайте преждевременного преобразования URL-адреса в путь файловой системы при использовании VirutalDocumentRoot). Основное изменение в поведении здесь заключается в том, что RewriteCond будет необходим для всех точек входа в приложение - аналогично строке / static.
EDIT
Вот мое последнее воплощение директив Rewrite в VirtualHost вне любого каталога директивы:
RewriteEngine on
RewriteCond %{REQUEST_URI} !^/static/
RewriteCond %{REQUEST_URI} !=/favicon.ico
RewriteCond %{REQUEST_URI} !=/robots.txt
RewriteRule ^/(.+)$ /index.php?q=$1 [NS,PT,L,QSA]
RewriteRule ^/$ /index.php [NS,PT,L,QSA]
Я добавил флаг NS
, чтобы избежать дополнительной внутренней оценки, и добавил вторую директиву RewriteRule
в пользу использования mod_dir и DirectoryIndex
. Мое приложение не ожидает параметра q = для корневого URL-адреса, иначе одно RewriteRule
из RewriteRule ^ / (. *) $ /Index.php?q=$1 [NS, PT, L, QSA ]
было бы достаточно, если бы приложение было обновлено, чтобы принимать пустой параметр q =
для корневого URL. Я могу сделать это в будущем.