Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Regex in Apache 'if' directive ... what's wrong here?

(A possible bug in Apache is now suspected ... see below.)

Here's the statements: (Apache 2.4)

<IfDefine !SERVER_TYPE>
    Define SERVER_TYPE prod
</IfDefine>
<If "${SERVER_TYPE} !~ /prod|demo|test/">   <===error here===
    Error "Define 'SERVER_TYPE' is hosed'"
</If>

Apache complains about the IF:

Cannot parse condition clause: syntax error, unexpected T_OP_NRE, expecting '('

I can guess that T_OP_NRE refers to "negated regular-expression" i.e. "!~" but I can't for the life of me figure out what's the syntax-error in that statement! (And, incidentally, "=~" produces [almost] the same message.)

Apache is recognizing the ${SERVER_TYPE} syntax as I can confirm if I misspell the identifier. The documentation for <DEFINE> expressly states that "${ident}" not "%{ident}" syntax should be used, as I have done.

What's wrong with my syntax, and why does Apache expect a left-parenthesis?


I am cautiously beginning to believe that this is actually a BUG(!) in Apache/2.4.12 because the parse-error only occurs when "${DEFINED_SYMBOL}" is used. It will complain and do all the right things if the symbol is not defined (so, it knows what it's looking at ...), but it gives a nonsensical (to me ...) message as-shown if, and only if, this construct is on the left-hand side.

An apparent workaround is to put the symbol in single quotes, e.g.:

<If "'${SERVER_TYPE}' != /prod/demo/test/">

... but so-far in my testing I don't think that it is matching the regex correctly. In fact, I'm not yet sure what is going on, because the following is considered to be a non-match ("true"):

<If "'prod' !~ /prod|demo|test/">

The regex syntax can be shown to be correct via this Perl one-liner:

perl -e 'my $var = "prod"; if ($var =~ /prod|demo|test/) {print "yes\n";}'

... which prints "yes."


P.S. The "${IDENT}" syntax is correct (versus "%{}", which is not) in the case of a Defined symbol.

like image 790
Mike Robinson Avatar asked Oct 30 '22 07:10

Mike Robinson


1 Answers

Try this syntax:

<If "'${SERVER_TYPE}' !~ m#(prod|demo|test)#">
    #Error "Define 'SERVER_TYPE' is hosed"
    RedirectMatch /old /new/
</If>
like image 92
anubhava Avatar answered Nov 09 '22 16:11

anubhava