我有一个RewriteCond
检查是否{QUERY_STRING}
包含正确版本号的方法,如果不包含则将用户重定向到正确的版本。
例如,如果 v0.7 是最新版本,则访问的用户http://localhost/?v=0.5
应该被重定向到,http://localhost/?v=0.7
但由于某种原因,如果我RewriteMap
在条件下使用,它不起作用......
这有效
RewriteMap versions txt:/var/www/html/version.txt
RewriteCond "%{QUERY_STRING}" !^v=0.7
RewriteRule "^/$" "/?v=${versions:version}" [R,L]
这不
RewriteMap versions txt:/var/www/html/version.txt
RewriteCond "%{QUERY_STRING}" !^v=${versions:version}
RewriteRule "^/$" "/?v=${versions:version}" [R,L]
version.txt 的内容
##
## version.txt -- rewriting map
## The version number written here will be mapped to the URL
##
##
version 0.7
答案1
RewriteCond "%{QUERY_STRING}" !^v=${versions:version}
这不起作用,因为条件模式(该RewriteCond
指令的第二个参数)是正则表达式,因此不支持变量扩展。(就像您不能使用$n
或%n
或服务器变量%(SERVER_VAR}
或环境变量形式的反向引用一样%{ENV:MY_ENV_VAR}
等形式的反向引用一样。)否则它会与 PCRE 正则表达式语法冲突。只有测试字符串(该指令的第一个参数RewriteCond
)和RewriteRule
代换参数支持变量扩展,因为这些参数是“常规”字符串,而不是正则表达式。
但是,您仍然可以执行所需的操作,并检查从 返回的正确版本号是否RewriteMap
存在于查询字符串的开头。相反,RewriteMap
在测试字符串(它支持变量扩展,因为这是一个“普通”字符串,而不是正则表达式)和比较这使用内部反向引用。
例如,将以下RewriteCond
内容改为:
RewriteCond %{QUERY_STRING}@${versions:version} !^v=([\d.]+)(?:&[^@]*)?@\1
在变量扩展之后,我们最终将形式为 的字符串[email protected]
与正则表达式进行匹配^v=([\d.]+)(?:&.*)?@\1
。\1
是对第一个捕获的子模式(即 URL 参数的值v
)的内部反向引用。 因此,这实际上将 URL 参数值与 从 返回的值进行匹配RewriteMap
。 然后整个表达式为否定(!
前缀),所以当条件满足时,它就成功了不是匹配,即版本号不同。
([\d.]+)
- 匹配查询字符串中的版本号,该版本号由一个或多个数字或文字点组成。例如。0.5
(?:&.*)?
- 匹配查询字符串的其余部分(如果有)。
@
只是一个任意字符串,它不会出现在查询字符串或“版本”字符串中。
您不需要用双引号括住参数,除非它们包含空格(即使这样,您也可以使用反斜杠转义空格)。因此,在此示例中,双引号完全是可选的。这同样适用于指令RewriteRule
。