Mod rewrite 如何在使用通配符的目录指令中使用apache2 mod_rewrite?

Mod rewrite 如何在使用通配符的目录指令中使用apache2 mod_rewrite?,mod-rewrite,apache2,Mod Rewrite,Apache2,我已经编写了一个web应用程序,它在一个专用服务器下运行,用于托管web应用程序。此web应用程序的实例在不同的域中可用,每个域都有自己的web应用程序文件副本,允许根据需要进行自定义 我正在Debian挤压下运行Apache/2.2.16 我在VirtualHost指令下执行所有配置,不使用.htaccess文件 为了简化apache配置,我想维护一个目录指令,如下所示: <Directory "/srv/www/*/public/"> RewriteEngine on R

我已经编写了一个web应用程序,它在一个专用服务器下运行,用于托管web应用程序。此web应用程序的实例在不同的域中可用,每个域都有自己的web应用程序文件副本,允许根据需要进行自定义

我正在Debian挤压下运行Apache/2.2.16

我在VirtualHost指令下执行所有配置,不使用.htaccess文件

为了简化apache配置,我想维护一个目录指令,如下所示:

<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>
<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>
问题是重写规则“uri”是文件系统路径而不是url路径,这导致查询字符串不正确:q=/srv/www/domain1/public/login

明确指定目录路径,如下所示:

<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>
<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>
我想我在Apache上遇到了一个bug,但如果不是这样,我做错了什么

虽然我很欣赏将方法更改为另一个可行的解决方案所带来的投入,但我会接受用我所采取的方法(例如不使用.htaccess)解决它的答案,除非能证明这种方法是不可解决的

那么,在通配符目录中使用RewriteCond/规则时,是否需要更改某些内容

好奇者的旁注:为了进一步简化,我使用了一个使用VirtualDocumentRoot的VirtualHost,但这与此无关,因为这个问题是通过使用“DocumentRoot”和在单个域下测试复制的

编辑

好的,我根据regilero的回答重新讨论了这个问题,下面是发生的情况-将重写从目录中移出会导致查询字符串从“login”更改为“/login”的轻微初始问题,这是通过将重写规则修改为:
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}来解决。但是,在使用VirtualDocumentRoot时,使用%{DOCUMENT_ROOT}不起作用

在我看来,%{DOCUMENT_ROOT}前缀是不必要的

编辑

请求文件名

与匹配的文件或脚本的完整本地文件系统路径 请求,如果服务器当时已经确定 请求文件名被引用。否则,如在中使用时 虚拟主机上下文,与请求URI的值相同

这就解释了文档根前缀的必要性

我已将重写规则更新为:

RewriteCond %{REQUEST_URI} !=/favicon.ico
RewriteCond %{REQUEST_URI} !=/robots.txt
RewriteCond %{REQUEST_URI} !^/static/
RewriteRule ^/(.+)$ /index.php?q=$1 [PT,L,QSA]
这可以正常工作(注意:PT标志是必要的,以避免在使用VirutalDocumentRoot时过早地将url路径转换为文件系统路径)。这里行为上的主要变化是,应用程序的所有入口点都需要一个RewriteCond,类似于/static行

编辑

以下是我在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=参数,否则,如果应用程序更新为接受根url的空
q=
参数,则使用
RewriteRule^/(.*)$/index.php的单个
RewriteRule
就足够了。我将来可能会这样做

这个问题很好,也很详细

您肯定遇到了一个bug,或者至少是一个未记录的重写规则域。文件指出:

  • 重写引擎可在.htaccess文件和中使用 部分,但有一些额外的复杂性
  • 要在此上下文中启用重写引擎,需要设置 必须启用“重写引擎打开”和“选项跟随符号链接”。如果 您的管理员已禁用对的FollowSymLinks的覆盖 用户的目录,则不能使用重写引擎。这一限制 出于安全原因需要
  • 在每个目录的.htaccess文件中使用重写引擎时 前缀(对于特定目录始终相同)将自动 为重写规则模式匹配而删除,并在之后自动添加 任何相对(不以斜杠或协议名称开头)替换 遇到规则集的结尾。有关更多信息,请参阅RewriteBase指令 有关将添加回相对替换的前缀的信息
因此,不提带有通配符的
指令将无法去除每个目录前缀这一事实。玩RewriteBase对你没有帮助,它是为了重建最终的Url而不是改变perdir的工作

但正如你在一开始看到的,“有一些额外的复杂性”的句子mod rewrite完成的目录操作比一般的目录外重写规则更慢、更复杂。这在本文中也有说明,主要是因为perdir条带操作。这意味着您还可以在VirtualHost的
部分之外编写重写规则

  • 它会更快
  • 它不会被这个错误击中
  • 如果某些不存在的文件不应映射到其他目录中的
    index.php?q=$1
    规则,则可能会产生一些副作用。但我很肯定这对你来说不是问题
因此,只需编写(不带通配符目录):

如果这会导致新的问题,让我知道它应该是有效的

编辑:

好的,对于OGOT,事实请求文件名尚未在VirtualHo中完全定义
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]
RewriteEngine on
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_FILENAME} !-f
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} !=/favicon.ico
RewriteCond %{REQUEST_URI} !=/robots.txt
RewriteRule ^/(.+)$ /index.php?q=$1 [L,QSA]
  RewriteCond %{LA-U:REQUEST_FILENAME} !-f [OR]
  RewriteCond %{LA-U:REQUEST_FILENAME} !/index.php
  RewriteCond %{LA-U:REQUEST_FILENAME} !-d
  RewriteCond %{REQUEST_URI} !=/favicon.ico
  RewriteCond %{REQUEST_URI} !=/robots.txt
  RewriteRule ^/(.+)$ /index.php?q=$1 [L,QSA]

  RewriteCond %{LA-U:REQUEST_FILENAME} /index.php
  RewriteRule ^/(.+)$ /index.php?q=$1 [L,QSA]