From d5174b9fcdfaa325960892575c358181c07d60f6 Mon Sep 17 00:00:00 2001
From: Eric Covener
Date: Sun, 1 Dec 2013 11:23:22 +0000
Subject: [PATCH] If the "value" argument is prefixed with expr=, parse it with
ap_expr rather than mod_headers' built-in format strings.
git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1546801 13f79535-47bb-0310-9956-ffa450edef68
---
CHANGES | 3 +++
docs/manual/mod/mod_headers.xml | 12 ++++++-----
modules/metadata/mod_headers.c | 35 ++++++++++++++++++++++++++++++---
3 files changed, 42 insertions(+), 8 deletions(-)
diff --git a/CHANGES b/CHANGES
index 1b94e347f7..41c5c31b95 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,6 +1,9 @@
-*- coding: utf-8 -*-
Changes with Apache 2.5.0
+ *) mod_headers: Allow the "value" parameter of Header and RequestHeader to
+ contain an ap_expr expression if prefixed with "expr=". [Eric Covener]
+
*) Add suspend_connection and resume_connection hooks to notify modules
when the thread/connection relationship changes. (Currently implemented
only for the Event MPM; should be implemented for all async MPMs.)
diff --git a/docs/manual/mod/mod_headers.xml b/docs/manual/mod/mod_headers.xml
index d10b6ef7c8..8e0087b4df 100644
--- a/docs/manual/mod/mod_headers.xml
+++ b/docs/manual/mod/mod_headers.xml
@@ -301,13 +301,12 @@ Header merge Cache-Control no-store env=NO_STORE
Header
Configure HTTP response headers
Header [condition] add|append|echo|edit|edit*|merge|set|unset|note
-header [value] [replacement]
+header [[expr=]value]] [replacement]
[early|env=[!]variable]|expr=expression]
server configvirtual host
directory.htaccess
FileInfo
-Default condition was temporarily changed to "always" in 2.3.9 and 2.3.10
This directive can replace, merge or remove HTTP response
@@ -421,9 +420,12 @@ Header merge Cache-Control no-store env=NO_STORE
add
a value is specified as the next argument.
If value
contains spaces, it should be surrounded by double quotes.
- value may be a character string, a string containing format
- specifiers or a combination of both. The following format specifiers
- are supported in value:
+ value may be a character string, a string containing
+ mod_headers specific format specifiers (and character
+ literals), or an ap_expr expression prefixed
+ with expr=
+
+ The following format specifiers are supported in value:
diff --git a/modules/metadata/mod_headers.c b/modules/metadata/mod_headers.c
index d4e694bf71..4608da7efe 100644
--- a/modules/metadata/mod_headers.c
+++ b/modules/metadata/mod_headers.c
@@ -133,6 +133,7 @@ typedef struct {
const char *condition_var;
const char *subs;
ap_expr_info_t *expr;
+ ap_expr_info_t *expr_out;
} header_entry;
/* echo_do is used for Header echo to iterate through the request headers*/
@@ -387,8 +388,9 @@ static char *parse_format_tag(apr_pool_t *p, format_tag *tag, const char **sa)
* contains a pointer to the function used to format the tag. Then save each
* tag in the tag array anchored in the header_entry.
*/
-static char *parse_format_string(apr_pool_t *p, header_entry *hdr, const char *s)
+static char *parse_format_string(cmd_parms *cmd, header_entry *hdr, const char *s)
{
+ apr_pool_t *p = cmd->pool;
char *res;
/* No string to parse with unset and echo commands */
@@ -400,6 +402,18 @@ static char *parse_format_string(apr_pool_t *p, header_entry *hdr, const char *s
s = hdr->subs;
}
+ if (!strncmp(s, "expr=", 5)) {
+ const char *err;
+ hdr->expr_out = ap_expr_parse_cmd(cmd, s+5,
+ AP_EXPR_FLAG_STRING_RESULT,
+ &err, NULL);
+ if (err) {
+ return apr_pstrcat(cmd->pool,
+ "Can't parse value expression : ", err, NULL);
+ }
+ return NULL;
+ }
+
hdr->ta = apr_array_make(p, 10, sizeof(format_tag));
while (*s) {
@@ -542,7 +556,7 @@ static APR_INLINE const char *header_inout_cmd(cmd_parms *cmd,
new->condition_var = condition_var;
new->expr = expr;
- return parse_format_string(cmd->pool, new, value);
+ return parse_format_string(cmd, new, value);
}
/* Handle all (xxx)Header directives */
@@ -584,14 +598,29 @@ static const char *header_cmd(cmd_parms *cmd, void *indirconf,
* (formatter) specific to the tag. Handlers return text strings.
* Concatenate the return from each handler into one string that is
* returned from this call.
+ * If the original value was prefixed with "expr=", processing is
+ * handled instead by ap_expr.
*/
static char* process_tags(header_entry *hdr, request_rec *r)
{
int i;
const char *s;
char *str = NULL;
+ format_tag *tag = NULL;
+
+ if (hdr->expr_out) {
+ const char *err;
+ const char *val;
+ val = ap_expr_str_exec(r, hdr->expr_out, &err);
+ if (err) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(02557)
+ "Can't evaluate value expression: %s", err);
+ return "";
+ }
+ return apr_pstrdup(r->pool, val);
+ }
- format_tag *tag = (format_tag*) hdr->ta->elts;
+ tag = (format_tag*) hdr->ta->elts;
for (i = 0; i < hdr->ta->nelts; i++) {
s = tag[i].func(r, tag[i].arg);
--
2.40.0