Как использовать apache2 mod_rewrite в директиве Каталога, которая использует подстановочные знаки?

Я написал веб-приложение, которое я запускаю на выделенном сервере для размещения веб-приложения. Экземпляры этого веб-приложения доступны в разных доменах, и каждый домен имеет свою собственную копию файлов веб-приложения, что позволяет при необходимости настраивать его.

Я запускаю 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. Я могу сделать это в будущем.

11
задан chris 15 June 2011 в 18:58
поделиться