From 165dc73d4d71c5d68beb5e904d91b280f08fccb6 Mon Sep 17 00:00:00 2001
From: Nick Kew
Date: Thu, 27 Aug 2009 01:02:42 +0000
Subject: [PATCH] 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
---
CHANGES | 3 ++
docs/manual/mod/mod_headers.xml | 54 +++++++++++++++++++++------------
modules/metadata/mod_headers.c | 29 +++++++++++++++---
3 files changed, 63 insertions(+), 23 deletions(-)
diff --git a/CHANGES b/CHANGES
index 2f07200672..eb887ad3f0 100644
--- a/CHANGES
+++ b/CHANGES
@@ -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
Cache-Control: no-cache, no-cache, no-store
+
+ Set a test cookie if and only if the client didn't send us a cookie
+
+ Header set Set-Cookie testcookie !$req{Cookie}
+
+
@@ -258,15 +264,20 @@ headers
replacement string respectively.
The RequestHeader 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 early
- to specify early processing. If the
- environment
- variable specified in the env=...
argument
- exists (or if the environment variable does not exist and
- env=!...
is specified) then the action specified
- by the RequestHeader directive will take effect.
- Otherwise, the directive will have no effect on the request.
+ an additional argument, which may be any of:
+
+ early
+ - Specifies early processing.
+ env=[!]varname
+ - The directive is applied if and only if the environment variable
varname
exists.
+ A !
in front of varname
reverses the test,
+ so the directive applies only if varname
is unset.
+ expr
+ - 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 mod_filter page.
+
Except in early mode, the
RequestHeader directive is processed
@@ -404,16 +415,21 @@ headers
which is a regular expression,
and an additional replacement string.
- The Header 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 early
- to specify early processing. If the
- environment variable specified in the
- env=...
argument exists (or if the environment
- variable does not exist and env=!...
is specified)
- then the action specified by the Header directive
- will take effect. Otherwise, the directive will have no effect
- on the request.
+ The Header directive may be followed by
+ an additional argument, which may be any of:
+
+ early
+ - Specifies early processing.
+ env=[!]varname
+ - The directive is applied if and only if the environment variable
varname
exists.
+ A !
in front of varname
reverses the test,
+ so the directive applies only if varname
is unset.
+ expr
+ - 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 mod_filter page.
+
Except in early mode, the
Header 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 != '!') {
--
2.40.0