[PATCH] support for environment variables in ProxyPassReverse

Carsten Gaebler <[email protected]> Mon, 16 Jun 2003 18:14:34 +0200
Newsgroups gmane.comp.apache.mod-proxy
Message-ID <[email protected]>
Hi there,

the book "Linux Server Hacks" by Rob Flickenger contains an example on 
how to use environment variables with the ProxyPassReverse directive. Of 
course it doesn't work because it's not implemented. :-) But since it's 
very useful for the proxy I'm maintaining and would also strip down this 
ugly reverse mapping list in the URL Rewriting Guide, I wrote a patch 
for Apache 1.3.27.

Basically it allows you to setup something like this:

RewriteRule  ^/(.*)/  http://$1/  [P,E=WHERETO:$1]
ProxyPassReverse  /%{ENV:WHERETO}/  http://%{ENV:WHERETO}/

The logical consequence would be for ProxyPass to support that, too. But 
  since this directive is handled in a different file and I don't know a 
centralized place to put the expand_vars() function, I didn't do that.

Feel free to send comments.

Regards
Carsten.
proxypassreverse-env.patch (text/plain, 3.7 KB)
--- src/modules/proxy/proxy_http.c.orig	Tue Sep  3 09:12:46 2002
+++ src/modules/proxy/proxy_http.c	Mon Jun 16 14:36:49 2003
@@ -114,6 +114,68 @@
     return OK;
 }
 
+/* Substitute %{ENV:VARIABLE} with the value of the environment variable */
+/* VARIABLE (enhancement of the ProxyPassReverse directive).             */
+/* I found this "feature" in the first edition of Rob Flickenger's       */
+/* Linux Server Hacks book (O'Reilly) but it wasn't actually supported   */
+/* by Apache, so I implemented it. :-)                                   */
+static const char *expand_vars(request_rec *r, const char* s)
+{
+    const char* p;
+    char* var_start;
+    char* var_end;
+    char* var;
+    const char* value;
+    array_header* result_array;
+
+    result_array = ap_make_array(r->pool, 4, sizeof(char *));
+    p = s;
+
+    while ((var_start = strstr(p, "%{ENV:")) != NULL) {
+        var_start += 6;
+
+        if ((var_end = strchr(var_start, '}')) == NULL) {
+            ap_log_error(APLOG_MARK, APLOG_ERR, r->server,
+                         "proxy: missing closing '}' in ENV expression: %s",
+                         s);
+            return s;
+        }
+
+        var = ap_pstrndup(r->pool, var_start, var_end - var_start);
+
+        /* get env-variable from the parent Apache process */
+        /* first try the internal Apache notes structure */
+        value = ap_table_get(r->notes, var);
+        /* second try the internal Apache env structure */
+        if (value == NULL) {
+            value = ap_table_get(r->subprocess_env, var);
+            /* third try the external OS env */
+            if (value == NULL) {
+                value = getenv(var);
+                if (value == NULL) {
+                    value = "";
+                    ap_log_error(APLOG_MARK, APLOG_WARNING, r->server,
+                                 "proxy: environment variable %s is empty",
+                                 var);
+                }
+            }
+        }
+      
+        *((const char **) ap_push_array(result_array)) =
+            ap_pstrndup(r->pool, p, var_start - p - 6);
+        
+        *((const char **) ap_push_array(result_array)) = value;
+
+        p = var_end + 1;
+    }
+
+    if ((p != NULL) && (*p != '\0')) {
+        *((const char **) ap_push_array(result_array)) = p;
+    }
+
+    return ap_array_pstrcat(r->pool, result_array, '\0');
+}
+
 /* handle the conversion of URLs in the ProxyPassReverse function */
 static const char *proxy_location_reverse_map(request_rec *r, const char *url)
 {
@@ -122,15 +184,25 @@
     struct proxy_alias *ent;
     int i, l1, l2;
     char *u;
+    const char* fake;
+    const char* real;
 
     sconf = r->server->module_config;
     conf = (proxy_server_conf *)ap_get_module_config(sconf, &proxy_module);
     l1 = strlen(url);
     ent = (struct proxy_alias *)conf->raliases->elts;
     for (i = 0; i < conf->raliases->nelts; i++) {
-        l2 = strlen(ent[i].real);
-        if (l1 >= l2 && strncmp(ent[i].real, url, l2) == 0) {
-            u = ap_pstrcat(r->pool, ent[i].fake, &url[l2], NULL);
+        ap_log_error(APLOG_MARK, APLOG_DEBUG, r->server,
+                     "proxy: pre_expand_vars: real: %s, fake: %s",
+                     ent[i].real, ent[i].fake);
+        fake = expand_vars(r, ent[i].fake);
+        real = expand_vars(r, ent[i].real);
+        ap_log_error(APLOG_MARK, APLOG_DEBUG, r->server,
+                     "proxy: post_expand_vars: real: %s, fake: %s",
+                     real, fake);
+        l2 = strlen(real);
+        if (l1 >= l2 && strncmp(real, url, l2) == 0) {
+            u = ap_pstrcat(r->pool, fake, &url[l2], NULL);
             return ap_construct_url(r->pool, u, r);
         }
     }