htaccess RewriteCond:为什么服务器变量不匹配自身?

htaccess RewriteCond: Why doesn't a server variable match itself?

也许更好的问题是,有没有办法在匹配字符串中使用服务器变量?

例如,我无法理解为什么这无法匹配:

RewriteCond %{REQUEST_URI} %{REQUEST_URI} 

首先,两点。

  1. 我知道这种情况没有任何意义。
  2. 我知道我对 htaccess 和正则表达式知之甚少。

我想要的是将这个URLwww.example.com/dir/path/info一般地变成www.example .com/dir?foo=/path/info 用于引导。

我试图通过从 URL 中最深的实际目录中删除额外的路径信息来完成此操作。我正在尝试使用这段代码来测试前提:

RewriteEngine On
Options -Multiviews -Indexes +FollowSymLinks   
RewriteBase /
DirectorySlash Off

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_URI} (.+)%{PATH_INFO}
RewriteRule ^(.+?) index.php?dir=%1&path=%2 [L]

运气不好。为了排除故障,我将其简化为:

RewriteCond %{PATH_INFO} (.+)
RewriteRule ^(.+?) index.php?dir=%1 [L]

正如预期的那样,查询返回了 foo='/path/info'

所以我尝试了这个我认为无论如何都会匹配的: RewriteCond %{PATH_INFO} %{PATH_INFO}

最后一次尝试失败了,我尝试捕获字符串:

RewriteCond %{PATH_INFO} (.+)
RewriteCond %{PATH_INFO} %1

那也没有找到让我百思不得其解的搭配。 %1 应该是完整的 %{PATH_INFO} 字符串。怎么会和自己不匹配???

我认为这无关紧要,但我在 FastCGI 的 Windows7 上使用 XAMPP。

重写 pattern 参数只允许正则表达式(Condpattern 也有用于测试和比较的特殊标志):

RewriteCond TestString CondPattern
重写规则模式替换

像 %{REQUEST_URI} 这样的服务器变量只能在 Teststring 和 Substitution 中使用。以下文档概述了这种用法:

http://httpd.apache.org/docs/2.4/mod/mod_rewrite.html#rewritecond http://httpd.apache.org/docs/2.4/mod/mod_rewrite.html#rewriterule

如果这会进入你的主 .htaccess,也许试试:

RewriteCond %{REQUEST_URI} !index\.php$
RewriteRule ^([^/]+)/(.+)$ index.php?dir=/&path=/ [L]

再举两个例子:

示例 1

RewriteBase /
RewriteRule ^(.+/)?index.php(/.+) index.php?dir=/&path= [R,L]

示例 2

RewriteBase /
RewriteRule ^((.+/)?index.php)(/.+) ?path= [R,L]

示例 3

RewriteBase /
RewriteRule ^(.+/)?(.+\.php)(/.+) ?foo= [R,L]

这些都是外部重写所以你可以在浏览器地址看到结果。要恢复为内部重写,只需删除 [R] 标志

好的,我找到了实现这个目标的方法。

基本上我是想比较两个服务器变量。 htaccess 不会那样做。我想提取指向实际文件或文件夹的 "pretty" url 的一部分。变量 ${SCRIPT_URL} 应该这样做,但它要么贬值要么不可靠。解决方法是将两个变量都放在测试字符串中,并使用正则表达式反向引用来查找重复点。

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME}.php -f
RewriteCond %{REQUEST_URI}%{PATH_INFO} (.*?)(/.+)$  
RewriteRule ^(.*)$ %1.php?strappath=%2 [QSA,END]

在上面的示例中,%1 将是文件的 uri,%2 将是 URI 之后的剩余路径,重复 %{PATH_INFO}。

没有额外路径信息时遵循此规则

RewriteCond %{REQUEST_FILENAME}.php -f
RewriteRule ^(.+?)$ .php [QSA,END]

如果没有找到 .php 文件,我需要该目录的索引并将未找到的文件名添加到路径信息中。这有点棘手。

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME}.php !-f
RewriteCond %{REQUEST_FILENAME} ^(.*)(/.+)$
RewriteCond %1 -d
RewriteCond %1/index.php -f
RewriteCond %{REQUEST_URI}%{PATH_INFO} ^(.*?)(/.+)$ [OR]
RewriteCond %{REQUEST_URI} ^(/.+)(/.+)?$
RewriteCond %1 ^(.*)(/.+)$
RewriteRule ^(.*)$ %1/index.php?strappath=%2%{PATH_INFO} [QSA,END]

以上部分无法捕获直接指向具有 index.php 的现有文件夹的 url,因此要捕获那些:

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} -d
RewriteCond %{REQUEST_FILENAME}/index.php -f
RewriteCond ^(.+)$ /index.php [QSA,END]

我怀疑有人会觉得这个有用,但我看到这个问题的变体被一遍又一遍地问,但没有给出有效的解决方案。