diff options
author | Nick Kew <niq@apache.org> | 2009-08-27 03:02:42 +0200 |
---|---|---|
committer | Nick Kew <niq@apache.org> | 2009-08-27 03:02:42 +0200 |
commit | 165dc73d4d71c5d68beb5e904d91b280f08fccb6 (patch) | |
tree | 68acabf687245a2deb83534733e07cac88a36fe3 | |
parent | Reintroduce an optimisation lost in some cut and paste. The cache lock (diff) | |
download | apache2-165dc73d4d71c5d68beb5e904d91b280f08fccb6.tar.xz apache2-165dc73d4d71c5d68beb5e904d91b280f08fccb6.zip |
mod_headers: generalise the envclause to support conditional
header rules via ap_expr.
git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@808240 13f79535-47bb-0310-9956-ffa450edef68
-rw-r--r-- | CHANGES | 3 | ||||
-rw-r--r-- | docs/manual/mod/mod_headers.xml | 54 | ||||
-rw-r--r-- | modules/metadata/mod_headers.c | 29 |
3 files changed, 63 insertions, 23 deletions
@@ -2,6 +2,9 @@ Changes with Apache 2.3.3 + *) mod_headers: generalise the envclause to support expression + evaluation with ap_expr parser [Nick Kew] + *) mod_cache: Introduce the thundering herd lock, a mechanism to keep the flood of requests at bay that strike a backend webserver as a cached entity goes stale. [Graham Leggett] diff --git a/docs/manual/mod/mod_headers.xml b/docs/manual/mod/mod_headers.xml index 91674c9d36..8fd54a4bda 100644 --- a/docs/manual/mod/mod_headers.xml +++ b/docs/manual/mod/mod_headers.xml @@ -181,6 +181,12 @@ headers</description> Cache-Control: no-cache, no-cache, no-store </example> </li> + <li> + Set a test cookie if and only if the client didn't send us a cookie + <example> + Header set Set-Cookie testcookie !$req{Cookie} + </example> + </li> </ol> </section> @@ -258,15 +264,20 @@ headers</description> replacement string respectively.</p> <p>The <directive>RequestHeader</directive> directive may be followed by - an additional argument, which may be used to specify conditions under - which the action will be taken, or may be the keyword <code>early</code> - to specify <a href="#early">early processing</a>. If the - <a href="../env.html">environment - variable</a> specified in the <code>env=<var>...</var></code> argument - exists (or if the environment variable does not exist and - <code>env=!<var>...</var></code> is specified) then the action specified - by the <directive>RequestHeader</directive> directive will take effect. - Otherwise, the directive will have no effect on the request.</p> + an additional argument, which may be any of:</p> + <dl> + <dt><code>early</code></dt> + <dd>Specifies <a href="#early">early processing</a>.</dd> + <dt><code>env=[!]varname</code></dt> + <dd>The directive is applied if and only if the <a href="../env.html" + >environment variable</a> <code>varname</code> exists. + A <code>!</code> in front of <code>varname</code> reverses the test, + so the directive applies only if <code>varname</code> is unset.</dd> + <dt><code>expr</code></dt> + <dd>An string that matches neither of the above is parsed as an + expression. Details of expression syntax and evaluation are + currently best documented on the <module>mod_filter</module> page.</dd> + </dl> <p>Except in <a href="#early">early</a> mode, the <directive>RequestHeader</directive> directive is processed @@ -404,16 +415,21 @@ headers</description> which is a <glossary ref="regex">regular expression</glossary>, and an additional <var>replacement</var> string.</p> - <p>The <directive>Header</directive> directive may be followed by an - an additional argument, which may be used to specify conditions under - which the action will be taken, or may be the keyword <code>early</code> - to specify <a href="#early">early processing</a>. If the - <a href="../env.html">environment variable</a> specified in the - <code>env=<var>...</var></code> argument exists (or if the environment - variable does not exist and <code>env=!<var>...</var></code> is specified) - then the action specified by the <directive>Header</directive> directive - will take effect. Otherwise, the directive will have no effect - on the request.</p> + <p>The <directive>Header</directive> directive may be followed by + an additional argument, which may be any of:</p> + <dl> + <dt><code>early</code></dt> + <dd>Specifies <a href="#early">early processing</a>.</dd> + <dt><code>env=[!]varname</code></dt> + <dd>The directive is applied if and only if the <a href="../env.html" + >environment variable</a> <code>varname</code> exists. + A <code>!</code> in front of <code>varname</code> reverses the test, + so the directive applies only if <code>varname</code> is unset.</dd> + <dt><code>expr</code></dt> + <dd>An string that matches neither of the above is parsed as an + expression. Details of expression syntax and evaluation are + currently best documented on the <module>mod_filter</module> page.</dd> + </dl> <p>Except in <a href="#early">early</a> mode, the <directive>Header</directive> directives are processed just diff --git a/modules/metadata/mod_headers.c b/modules/metadata/mod_headers.c index b65fbfd077..c9c73c7db9 100644 --- a/modules/metadata/mod_headers.c +++ b/modules/metadata/mod_headers.c @@ -81,6 +81,7 @@ #include "http_log.h" #include "util_filter.h" #include "http_protocol.h" +#include "ap_expr.h" #include "mod_ssl.h" /* for the ssl_var_lookup optional function defn */ @@ -125,6 +126,7 @@ typedef struct { ap_regex_t *regex; const char *condition_var; const char *subs; + ap_parse_node_t *expr; } header_entry; /* echo_do is used for Header echo to iterate through the request headers*/ @@ -391,6 +393,7 @@ static APR_INLINE const char *header_inout_cmd(cmd_parms *cmd, const char *condition_var = NULL; const char *colon; header_entry *new; + ap_parse_node_t *expr = NULL; apr_array_header_t *fixup = (cmd->info == &hdr_in) ? dirconf->fixup_in : (cmd->info == &hdr_err) @@ -472,10 +475,7 @@ static APR_INLINE const char *header_inout_cmd(cmd_parms *cmd, if (strcasecmp(envclause, "early") == 0) { condition_var = condition_early; } - else { - if (strncasecmp(envclause, "env=", 4) != 0) { - return "error: envclause should be in the form env=envar"; - } + else if (strncasecmp(envclause, "env=", 4) == 0) { if ((envclause[4] == '\0') || ((envclause[4] == '!') && (envclause[5] == '\0'))) { return "error: missing environment variable name. " @@ -483,6 +483,13 @@ static APR_INLINE const char *header_inout_cmd(cmd_parms *cmd, } condition_var = envclause + 4; } + else { + int err = 0; + expr = ap_expr_parse(cmd->pool, envclause, &err); + if (err) { + return "Can't parse envclause/expression"; + } + } } if ((colon = ap_strchr_c(hdr, ':'))) { @@ -491,6 +498,7 @@ static APR_INLINE const char *header_inout_cmd(cmd_parms *cmd, new->header = hdr; new->condition_var = condition_var; + new->expr = expr; return parse_format_string(cmd->pool, new, value); } @@ -620,6 +628,19 @@ static void do_headers_fixup(request_rec *r, apr_table_t *headers, else if (early && (envar != condition_early)) { continue; } + /* Do we have an expression to evaluate? */ + else if (hdr->expr != NULL) { + int err = 0; + int eval = ap_expr_eval(r, hdr->expr, &err, NULL, + ap_expr_string, NULL); + if (err) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, + "Failed to evaluate expression - ignoring"); + } + else if (!eval) { + continue; + } + } /* Have any conditional envar-controlled Header processing to do? */ else if (envar && !early) { if (*envar != '!') { |