]> granicus.if.org Git - apache/commitdiff
Follow up to r1810605.
authorYann Ylavic <ylavic@apache.org>
Wed, 4 Oct 2017 17:08:13 +0000 (17:08 +0000)
committerYann Ylavic <ylavic@apache.org>
Wed, 4 Oct 2017 17:08:13 +0000 (17:08 +0000)
Update docs' BNF, provide a short description of the new %{::} syntax and
a few examples. To be continued..

git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1811111 13f79535-47bb-0310-9956-ffa450edef68

docs/manual/expr.xml

index 2431f9b1132aa7c9a153cc8a1885890c4ea9ad5f..89811890f1d208ec50c407d705c2fec870e7319f 100644 (file)
       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>&amp;&amp;</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>&amp;&amp;</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
@@ -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        ::= &lt;any OCTET except CTLs&gt;
+DIGIT       ::= &lt;any US-ASCII digit "0".."9"&gt;
 </pre>
 </blockquote>
 
@@ -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">
@@ -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>
 
@@ -654,6 +710,14 @@ Header set foo-checksum "expr=%{md5:foo}"
 # This delays the evaluation of the condition clause compared to &lt;If&gt;
 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>
 
@@ -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