Loading docs/manual/expr.xml +93 −29 Original line number Diff line number Diff line Loading @@ -79,29 +79,41 @@ Form</a> (BNF) is a notation technique for context-free grammars, often used to describe the syntax of languages used in computing. In most cases, expressions are used to express boolean values. For these, the starting point in the BNF is <code>expr</code>. However, a few directives like <directive module="mod_log_debug">LogMessage</directive> accept expressions For these, the starting point in the BNF is <code>cond</code>. Directives like <directive module="core">ErrorDocument</directive>, <directive module="mod_authz_core">Require</directive>, <directive module="mod_authn_core">AuthName</directive>, <directive module="mod_alias">Redirect</directive>, <directive module="mod_headers">Header</directive>, <directive module="mod_crypto">CryptoKey</directive> or <directive module="mod_log_debug">LogMessage</directive> accept expressions that evaluate to a string value. For those, the starting point in the BNF is <code>string</code>. </p> <blockquote> <pre> expr ::= "<strong>true</strong>" | "<strong>false</strong>" | "<strong>!</strong>" expr | expr "<strong>&&</strong>" expr | expr "<strong>||</strong>" expr | "<strong>(</strong>" expr "<strong>)</strong>" expr ::= cond | string string ::= substring | string substring cond ::= "<strong>true</strong>" | "<strong>false</strong>" | "<strong>!</strong>" cond | cond "<strong>&&</strong>" cond | cond "<strong>||</strong>" cond | comp | "<strong>(</strong>" cond "<strong>)</strong>" comp ::= stringcomp | integercomp | unaryop word | word binaryop word | word "<strong>in</strong>" "<strong>{</strong>" wordlist "<strong>}</strong>" | word "<strong>in</strong>" listfunction | word "<strong>in</strong>" listfunc | word "<strong>=~</strong>" regex | word "<strong>!~</strong>" regex | word "<strong>in</strong>" "<strong>{</strong>" list "<strong>}</strong>" stringcomp ::= word "<strong>==</strong>" word Loading @@ -118,35 +130,64 @@ integercomp ::= word "<strong>-eq</strong>" word | word "<strong>eq</strong>" wo | word "<strong>-gt</strong>" word | word "<strong>gt</strong>" word | word "<strong>-ge</strong>" word | word "<strong>ge</strong>" word wordlist ::= word | wordlist "<strong>,</strong>" word word ::= word "<strong>.</strong>" word | digit word ::= digits | "<strong>'</strong>" string "<strong>'</strong>" | "<strong>"</strong>" string "<strong>"</strong>" | '<strong>"</strong>' string '<strong>"</strong>' | word "<strong>.</strong>" word | variable | rebackref | sub | join | function | "<strong>(</strong>" word "<strong>)</strong>" string ::= stringpart | string stringpart list ::= split | listfunc | "<strong>{</strong>" words "<strong>}</strong>" | "<strong>(</strong>" list "<strong>)</strong>" stringpart ::= cstring substring ::= cstring | variable | rebackref cstring ::= ... digit ::= [0-9]+ variable ::= "<strong>%{</strong>" varname "<strong>}</strong>" | "<strong>%{</strong>" funcname "<strong>:</strong>" funcargs "<strong>}</strong>" | "<strong>%{:</strong>" word "<strong>:}</strong>" | "<strong>%{:</strong>" cond "<strong>:}</strong>" | rebackref sub ::= "<strong>sub</strong>" ["<strong>(</strong>"] regsub "<strong>,</strong>" word ["<strong>)</strong>"] join ::= "<strong>join</strong>" ["<strong>(</strong>"] list ["<strong>)</strong>"] | "<strong>join</strong>" ["<strong>(</strong>"] list "<strong>,</strong>" word ["<strong>)</strong>"] split ::= "<strong>split</strong>" ["<strong>(</strong>"] regany "<strong>,</strong>" list ["<strong>)</strong>"] | "<strong>split</strong>" ["<strong>(</strong>"] regany "<strong>,</strong>" word ["<strong>)</strong>"] function ::= funcname "<strong>(</strong>" words "<strong>)</strong>" rebackref ::= "<strong>$</strong>" [0-9] listfunc ::= listfuncname "<strong>(</strong>" words "<strong>)</strong>" function ::= funcname "<strong>(</strong>" wordlist "<strong>)</strong>" words ::= word | word "<strong>,</strong>" list listfunction ::= listfuncname "<strong>(</strong>" word "<strong>)</strong>" regex ::= "<strong>/</strong>" regpattern "<strong>/</strong>" [regflags] | "<strong>m</strong>" regsep regpattern regsep [regflags] regsub ::= "<strong>s</strong>" regsep regpattern regsep string regsep [regflags] regany ::= regex | regsub regsep ::= "/" | "#" | "$" | "%" | "^" | "|" | "?" | "!" | "'" | '"' | "," | ";" | ":" | "." | "_" | "-" regflags ::= 1*("i" | "s" | "m" | "g") regpattern ::= cstring ; except enclosing <em>regsep</em> rebackref ::= "<strong>$</strong>" DIGIT digits ::= 1*(DIGIT) cstring ::= 0*(TEXT) TEXT ::= <any OCTET except CTLs> DIGIT ::= <any US-ASCII digit "0".."9"> </pre> </blockquote> Loading Loading @@ -335,6 +376,21 @@ listfunction ::= listfuncname "<strong>(</strong>" word "<strong>)</strong>" <p>Some modules register additional variables, see e.g. <module>mod_ssl</module>.</p> <p>Any variable can be embedded in a <em>string</em>, both in quoted strings from boolean expressions but also in string expressions, resulting in the concatenation of the constant and dynamic parts as expected.</p> <p>There exists another form of variables (temporaries) expressed like <code>%{:<em>word</em>:}</code> and which allow embedding of the more powerful <em>word</em> syntax (and constructs) in both type of expressions, without colliding with the constant part of such strings. They are mainly useful in string expressions though, since the <em>word</em> is directly available in boolean expressions already. By using this form of variables, one can evaluate regexes, substitutions, join and/or split strings and lists in the scope of string expressions, hence construct complex strings dynamically.</p> </section> <section id="binop"> Loading Loading @@ -582,7 +638,7 @@ listfunction ::= listfuncname "<strong>(</strong>" word "<strong>)</strong>" <p>In addition to string-valued functions, there are also list-valued functions which take one string as argument and return a wordlist, i.e. a list of strings. The wordlist can be used with the list, i.e. a list of strings. The list can be used with the special <code>-in</code> operator. Functions names are not case sensitive. Modules may register additional functions.</p> Loading Loading @@ -654,6 +710,14 @@ Header set foo-checksum "expr=%{md5:foo}" # This delays the evaluation of the condition clause compared to <If> Header always set CustomHeader my-value "expr=%{REQUEST_URI} =~ m#^/special_path\.php$#" # Add a header to forward client's certificate SAN to some backend RequestHeader set X-Client-SAN "expr=%{:join PeerExtList('subjectAltName'):}" # Require that the remote IP be in the client's certificate SAN Require expr %{REMOTE_ADDR} -in split s/.*?IP Address:([^,]+)/$1/, PeerExtList('subjectAltName') # or alternatively: Require expr "IP Address:%{REMOTE_ADDR}" -in split/, /, join PeerExtList('subjectAltName') </highlight> </section> Loading @@ -666,7 +730,7 @@ Header always set CustomHeader my-value "expr=%{REQUEST_URI} =~ m#^/special_path <tr><th>Name</th><th>Alternative</th> <th>Description</th></tr> <tr><td><code>-in</code></td> <td><code>in</code></td> <td>string contained in wordlist</td></tr> <td>string contained in list</td></tr> <tr><td><code>/regexp/</code></td> <td><code>m#regexp#</code></td> <td>Regular expression (the second form allows different Loading Loading
docs/manual/expr.xml +93 −29 Original line number Diff line number Diff line Loading @@ -79,29 +79,41 @@ Form</a> (BNF) is a notation technique for context-free grammars, often used to describe the syntax of languages used in computing. In most cases, expressions are used to express boolean values. For these, the starting point in the BNF is <code>expr</code>. However, a few directives like <directive module="mod_log_debug">LogMessage</directive> accept expressions For these, the starting point in the BNF is <code>cond</code>. Directives like <directive module="core">ErrorDocument</directive>, <directive module="mod_authz_core">Require</directive>, <directive module="mod_authn_core">AuthName</directive>, <directive module="mod_alias">Redirect</directive>, <directive module="mod_headers">Header</directive>, <directive module="mod_crypto">CryptoKey</directive> or <directive module="mod_log_debug">LogMessage</directive> accept expressions that evaluate to a string value. For those, the starting point in the BNF is <code>string</code>. </p> <blockquote> <pre> expr ::= "<strong>true</strong>" | "<strong>false</strong>" | "<strong>!</strong>" expr | expr "<strong>&&</strong>" expr | expr "<strong>||</strong>" expr | "<strong>(</strong>" expr "<strong>)</strong>" expr ::= cond | string string ::= substring | string substring cond ::= "<strong>true</strong>" | "<strong>false</strong>" | "<strong>!</strong>" cond | cond "<strong>&&</strong>" cond | cond "<strong>||</strong>" cond | comp | "<strong>(</strong>" cond "<strong>)</strong>" comp ::= stringcomp | integercomp | unaryop word | word binaryop word | word "<strong>in</strong>" "<strong>{</strong>" wordlist "<strong>}</strong>" | word "<strong>in</strong>" listfunction | word "<strong>in</strong>" listfunc | word "<strong>=~</strong>" regex | word "<strong>!~</strong>" regex | word "<strong>in</strong>" "<strong>{</strong>" list "<strong>}</strong>" stringcomp ::= word "<strong>==</strong>" word Loading @@ -118,35 +130,64 @@ integercomp ::= word "<strong>-eq</strong>" word | word "<strong>eq</strong>" wo | word "<strong>-gt</strong>" word | word "<strong>gt</strong>" word | word "<strong>-ge</strong>" word | word "<strong>ge</strong>" word wordlist ::= word | wordlist "<strong>,</strong>" word word ::= word "<strong>.</strong>" word | digit word ::= digits | "<strong>'</strong>" string "<strong>'</strong>" | "<strong>"</strong>" string "<strong>"</strong>" | '<strong>"</strong>' string '<strong>"</strong>' | word "<strong>.</strong>" word | variable | rebackref | sub | join | function | "<strong>(</strong>" word "<strong>)</strong>" string ::= stringpart | string stringpart list ::= split | listfunc | "<strong>{</strong>" words "<strong>}</strong>" | "<strong>(</strong>" list "<strong>)</strong>" stringpart ::= cstring substring ::= cstring | variable | rebackref cstring ::= ... digit ::= [0-9]+ variable ::= "<strong>%{</strong>" varname "<strong>}</strong>" | "<strong>%{</strong>" funcname "<strong>:</strong>" funcargs "<strong>}</strong>" | "<strong>%{:</strong>" word "<strong>:}</strong>" | "<strong>%{:</strong>" cond "<strong>:}</strong>" | rebackref sub ::= "<strong>sub</strong>" ["<strong>(</strong>"] regsub "<strong>,</strong>" word ["<strong>)</strong>"] join ::= "<strong>join</strong>" ["<strong>(</strong>"] list ["<strong>)</strong>"] | "<strong>join</strong>" ["<strong>(</strong>"] list "<strong>,</strong>" word ["<strong>)</strong>"] split ::= "<strong>split</strong>" ["<strong>(</strong>"] regany "<strong>,</strong>" list ["<strong>)</strong>"] | "<strong>split</strong>" ["<strong>(</strong>"] regany "<strong>,</strong>" word ["<strong>)</strong>"] function ::= funcname "<strong>(</strong>" words "<strong>)</strong>" rebackref ::= "<strong>$</strong>" [0-9] listfunc ::= listfuncname "<strong>(</strong>" words "<strong>)</strong>" function ::= funcname "<strong>(</strong>" wordlist "<strong>)</strong>" words ::= word | word "<strong>,</strong>" list listfunction ::= listfuncname "<strong>(</strong>" word "<strong>)</strong>" regex ::= "<strong>/</strong>" regpattern "<strong>/</strong>" [regflags] | "<strong>m</strong>" regsep regpattern regsep [regflags] regsub ::= "<strong>s</strong>" regsep regpattern regsep string regsep [regflags] regany ::= regex | regsub regsep ::= "/" | "#" | "$" | "%" | "^" | "|" | "?" | "!" | "'" | '"' | "," | ";" | ":" | "." | "_" | "-" regflags ::= 1*("i" | "s" | "m" | "g") regpattern ::= cstring ; except enclosing <em>regsep</em> rebackref ::= "<strong>$</strong>" DIGIT digits ::= 1*(DIGIT) cstring ::= 0*(TEXT) TEXT ::= <any OCTET except CTLs> DIGIT ::= <any US-ASCII digit "0".."9"> </pre> </blockquote> Loading Loading @@ -335,6 +376,21 @@ listfunction ::= listfuncname "<strong>(</strong>" word "<strong>)</strong>" <p>Some modules register additional variables, see e.g. <module>mod_ssl</module>.</p> <p>Any variable can be embedded in a <em>string</em>, both in quoted strings from boolean expressions but also in string expressions, resulting in the concatenation of the constant and dynamic parts as expected.</p> <p>There exists another form of variables (temporaries) expressed like <code>%{:<em>word</em>:}</code> and which allow embedding of the more powerful <em>word</em> syntax (and constructs) in both type of expressions, without colliding with the constant part of such strings. They are mainly useful in string expressions though, since the <em>word</em> is directly available in boolean expressions already. By using this form of variables, one can evaluate regexes, substitutions, join and/or split strings and lists in the scope of string expressions, hence construct complex strings dynamically.</p> </section> <section id="binop"> Loading Loading @@ -582,7 +638,7 @@ listfunction ::= listfuncname "<strong>(</strong>" word "<strong>)</strong>" <p>In addition to string-valued functions, there are also list-valued functions which take one string as argument and return a wordlist, i.e. a list of strings. The wordlist can be used with the list, i.e. a list of strings. The list can be used with the special <code>-in</code> operator. Functions names are not case sensitive. Modules may register additional functions.</p> Loading Loading @@ -654,6 +710,14 @@ Header set foo-checksum "expr=%{md5:foo}" # This delays the evaluation of the condition clause compared to <If> Header always set CustomHeader my-value "expr=%{REQUEST_URI} =~ m#^/special_path\.php$#" # Add a header to forward client's certificate SAN to some backend RequestHeader set X-Client-SAN "expr=%{:join PeerExtList('subjectAltName'):}" # Require that the remote IP be in the client's certificate SAN Require expr %{REMOTE_ADDR} -in split s/.*?IP Address:([^,]+)/$1/, PeerExtList('subjectAltName') # or alternatively: Require expr "IP Address:%{REMOTE_ADDR}" -in split/, /, join PeerExtList('subjectAltName') </highlight> </section> Loading @@ -666,7 +730,7 @@ Header always set CustomHeader my-value "expr=%{REQUEST_URI} =~ m#^/special_path <tr><th>Name</th><th>Alternative</th> <th>Description</th></tr> <tr><td><code>-in</code></td> <td><code>in</code></td> <td>string contained in wordlist</td></tr> <td>string contained in list</td></tr> <tr><td><code>/regexp/</code></td> <td><code>m#regexp#</code></td> <td>Regular expression (the second form allows different Loading