I have a RewriteCond
that checks if {QUERY_STRING}
contains the right version number, if it doesn't then redirect users to the correct version.
For instance if v0.7 is the latest, users accessing http://localhost/?v=0.5
should be redirected to http://localhost/?v=0.7
but for some reason, if am using RewriteMap
in the conditions, it doesn't work...
This works
RewriteMap versions txt:/var/www/html/version.txt
RewriteCond "%{QUERY_STRING}" !^v=0.7
RewriteRule "^/$" "/?v=${versions:version}" [R,L]
This doesn't
RewriteMap versions txt:/var/www/html/version.txt
RewriteCond "%{QUERY_STRING}" !^v=${versions:version}
RewriteRule "^/$" "/?v=${versions:version}" [R,L]
Content of version.txt
##
## version.txt -- rewriting map
## The version number written here will be mapped to the URL
##
##
version 0.7
This doesn't work because the CondPattern (2nd argument to the
RewriteCond
directive) is a regex and consequently does not support variable expansion. (Just as you can't use backreferences of the form$n
or%n
or server variables%(SERVER_VAR}
or env vars%{ENV:MY_ENV_VAR}
etc.) It would otherwise conflict with the PCRE regex syntax. Only the TestString (first argument to theRewriteCond
directive) and theRewriteRule
substitution arguments support variable expansion, since these arguments are "regular" strings, not regex.However, you can still do what you require and check that the correct version number, as returned from the
RewriteMap
, is present at the start of the query string. Instead, expand the result of theRewriteMap
in the TestString (which does support variable expansion since this is an "ordinary" string, not a regex) and compare this using an internal backreference.For example, change the
RewriteCond
to read:After the variable expansion, we end up matching a string of the form
[email protected]
against the regex^v=([\d.]+)(?:&.*)?@\1
.\1
is an internal backreference to the first captured subpattern (ie. the value of thev
URL parameter). So, this effectively matches the URL parameter value against the value returned from theRewriteMap
. This whole expression is then negated (!
prefix) so it's successful when the condition does not match, ie. the version number is different.([\d.]+)
- Matches the version number in the query string, which consists of 1 or more digits or literal dots. eg.0.5
(?:&.*)?
- Matches the remainder of the query string (if any).@
is just an arbitrary string that does not otherwise occur in the query string or "version" string.You don't need to surround the arguments in double-quotes unless they contain spaces (even then you can backslash escape the spaces instead). So, the double quotes are entirely optional in this example. The same applies to the
RewriteRule
directive.