Я написал веб-приложение, которое запускаю на выделенном сервере для размещения веб-приложения. Экземпляры этого веб-приложения доступны в разных доменах, и у каждого домена есть своя собственная копия файлов веб-приложения, позволяющая при необходимости выполнить настройку.
Я использую Apache / 2.2.16 под Debian Squeeze.
Я делаю все настройки в соответствии с директивой 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 = Логин ):
[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 при использовании в каталоге с подстановочными знаками?
Примечание для любопытных: для дальнейшего упрощения я использую один VirtualHost с использованием VirtualDocumentRoot - однако это не связано, поскольку эта проблема реплицируется с использованием DocumentRoot и тестированием в одном домене.
EDIT
Хорошо, я пересмотрел это, основываясь на ответе regilero , и вот что происходит - перемещение перезаписанного, как есть, из Справочника приводит к небольшой начальной проблеме изменения строки запроса от "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
. Мое приложение ожидает, что для корневого URL не задан параметр q =, в противном случае будет достаточно одного RewriteRule
из RewriteRule ^/(.*)$ /index.php?q=$1 [NS,PT,L,QSA]
, если приложение будет обновлено, чтобы принять пустой параметр q=
для корневого URL. Я могу сделать это в будущем.