Environment Variable Interpolation in ProxyPass/Reverse

2006-07-12 Thread Nick Kew
This is a topic that's been discussed occasionally, though not
(AFAIR) on this list.

A few weeks back, I implemented a patch to support interpolating
per-request environment variables in reverse proxying directives.
Note that this goes beyond what mod_rewrite already supports,
because it also interpolates response headers per
ProxyPassReverse and family.

Do we want this in /trunk/ ?

-- 
Nick Kew
Index: proxy_util.c
===
--- proxy_util.c	(revision 421119)
+++ proxy_util.c	(working copy)
@@ -1015,6 +1015,7 @@
 PROXY_DECLARE(const char *) ap_proxy_location_reverse_map(request_rec *r,
   proxy_dir_conf *conf, const char *url)
 {
+proxy_req_conf *rconf;
 struct proxy_alias *ent;
 int i, l1, l2;
 char *u;
@@ -1023,9 +1024,18 @@
  * XXX FIXME: Make sure this handled the ambiguous case of the :PORT
  * after the hostname
  */
+if (r-proxyreq != PROXYREQ_REVERSE) {
+return url;
+}
 
 l1 = strlen(url);
-ent = (struct proxy_alias *)conf-raliases-elts;
+if (conf-interpolate_env == 1) {
+rconf = ap_get_module_config(r-request_config, proxy_module);
+ent = (struct proxy_alias *)rconf-raliases-elts;
+}
+else {
+ent = (struct proxy_alias *)conf-raliases-elts;
+}
 for (i = 0; i  conf-raliases-nelts; i++) {
 l2 = strlen(ent[i].real);
 if (l1 = l2  strncasecmp(ent[i].real, url, l2) == 0) {
@@ -1047,6 +1057,8 @@
 PROXY_DECLARE(const char *) ap_proxy_cookie_reverse_map(request_rec *r,
   proxy_dir_conf *conf, const char *str)
 {
+proxy_req_conf *rconf = ap_get_module_config(r-request_config,
+ proxy_module);
 struct proxy_alias *ent;
 size_t len = strlen(str);
 const char *newpath = NULL;
@@ -1061,6 +1073,10 @@
 int pdiff = 0;
 char *ret;
 
+if (r-proxyreq != PROXYREQ_REVERSE) {
+return str;
+}
+
/*
 * Find the match and replacement, but save replacing until we've done
 * both path and domain so we know the new strlen
@@ -1071,7 +1087,12 @@
 pathe = ap_strchr_c(pathp, ';');
 l1 = pathe ? (pathe - pathp) : strlen(pathp);
 pathe = pathp + l1 ;
-ent = (struct proxy_alias *)conf-cookie_paths-elts;
+if (conf-interpolate_env == 1) {
+ent = (struct proxy_alias *)rconf-cookie_paths-elts;
+}
+else {
+ent = (struct proxy_alias *)conf-cookie_paths-elts;
+}
 for (i = 0; i  conf-cookie_paths-nelts; i++) {
 l2 = strlen(ent[i].fake);
 if (l1 = l2  strncmp(ent[i].fake, pathp, l2) == 0) {
@@ -1088,7 +1109,12 @@
 domaine = ap_strchr_c(domainp, ';');
 l1 = domaine ? (domaine - domainp) : strlen(domainp);
 domaine = domainp + l1;
-ent = (struct proxy_alias *)conf-cookie_domains-elts;
+if (conf-interpolate_env == 1) {
+ent = (struct proxy_alias *)rconf-cookie_domains-elts;
+}
+else {
+ent = (struct proxy_alias *)conf-cookie_domains-elts;
+}
 for (i = 0; i  conf-cookie_domains-nelts; i++) {
 l2 = strlen(ent[i].fake);
 if (l1 = l2  strncasecmp(ent[i].fake, domainp, l2) == 0) {
Index: mod_proxy.c
===
--- mod_proxy.c	(revision 421119)
+++ mod_proxy.c	(working copy)
@@ -410,6 +410,57 @@
 return DECLINED;
 }
 
+static const char *proxy_interpolate(request_rec *r, const char *str)
+{
+/* Interpolate an env str in a configuration string
+ * Syntax ${var} -- value_of(var)
+ * Method: replace one var, and recurse on remainder of string
+ * Nothing clever here, and crap like nested vars may do silly things
+ * but we'll at least avoid sending the unwary into a loop
+ */
+const char *start;
+const char *end;
+const char *var;
+const char *val;
+const char *firstpart;
+
+start = ap_strstr(str, ${);
+if (start == NULL) {
+return str;
+}
+end = ap_strchr(start+2, '}');
+if (end == NULL) {
+return str;
+}
+/* OK, this is syntax we want to interpolate.  Is there such a var ? */
+var = apr_pstrndup(r-pool, start+2, end-(start+2));
+val = apr_table_get(r-subprocess_env, var);
+firstpart = apr_pstrndup(r-pool, str, (start-str));
+
+if (val == NULL) {
+return apr_pstrcat(r-pool, firstpart,
+   proxy_interpolate(r, end+1), NULL);
+}
+else {
+return apr_pstrcat(r-pool, firstpart, val,
+   proxy_interpolate(r, end+1), NULL);
+}
+}
+static apr_array_header_t *proxy_vars(request_rec *r,
+  apr_array_header_t *hdr)
+{
+int i;
+apr_array_header_t *ret = apr_array_make(r-pool, hdr-nelts,
+  

Re: Environment Variable Interpolation in ProxyPass/Reverse

2006-07-12 Thread Eli Marmor
I'm not a member, and I can't vote but only express my own needs, but
this is something that I've waited for a long time, and I even planned
to implement it, but Nick was faster...

Nick Kew wrote:
 
 This is a topic that's been discussed occasionally, though not
 (AFAIR) on this list.
 
 A few weeks back, I implemented a patch to support interpolating
 per-request environment variables in reverse proxying directives.
 Note that this goes beyond what mod_rewrite already supports,
 because it also interpolates response headers per
 ProxyPassReverse and family.
 
 Do we want this in /trunk/ ?

-- 
Eli Marmor
[EMAIL PROTECTED]
Netmask (El-Mar) Internet Technologies Ltd.
__
Tel.:   +972-9-766-1020  8 Yad-Harutzim St.
Fax.:   +972-9-766-1314  P.O.B. 7004
Mobile: +972-50-5237338  Kfar-Saba 44641, Israel