[PATCH] support for environment variables in ProxyPassReverse

[PATCH] support for environment variables in ProxyPassReverse

am 16.06.2003 18:14:34 von Carsten Gaebler

This is a multi-part message in MIME format.
--------------080307000004060702020300
Content-Type: text/plain; charset=us-ascii; format=flowed
Content-Transfer-Encoding: 7bit

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.

--------------080307000004060702020300
Content-Type: text/plain;
name="proxypassreverse-env.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
filename="proxypassreverse-env.patch"

--- 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);
}
}

--------------080307000004060702020300--

Re: [PATCH] support for environment variables in ProxyPassReverse

am 17.06.2003 17:24:50 von Graham Leggett

Carsten Gaebler wrote:

> 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.

Is it possible to create a patch for Apache v2.0?

Regards,
Graham
--
-----------------------------------------
minfrin@sharp.fm "There's a moon
over Bourbon Street
tonight..."

Re: [PATCH] support for environment variables in ProxyPassReverse

am 17.06.2003 17:42:28 von Carsten Gaebler

Graham Leggett wrote:
> Carsten Gaebler wrote:
>> wrote a patch for Apache 1.3.27.
>
> Is it possible to create a patch for Apache v2.0?

Sure. s/ap_/apr_/g should do, I guess. :-) Stay tuned.

cg.

Re: [PATCH] support for environment variables in ProxyPassReverse

am 18.06.2003 09:04:43 von Olivier DECKMYN

Any chance to see this patch included into Apache 1.3.28 ?

> Return-Path:
> Delivered-To: odeckmyn.list@teaser.fr
> Received: from musique.teaser.net (musique.teaser.net [213.91.2.11])
> by philo.teaser.net (lmtpd) with LMTP id 71259.152;
> Mon, 16 Jun 2003 18:14:40 +0200 (CEST)
> Received: from apache.org (daedalus.apache.org [208.185.179.12])
> by musique.teaser.net (Postfix) with SMTP id F3D8772523
> for ; Mon, 16 Jun 2003 18:14:39 +0200 (CEST)
> Received: (qmail 75585 invoked by uid 500); 16 Jun 2003 16:14:33 -0000
> Mailing-List: contact modproxy-dev-help@apache.org; run by ezmlm
> Precedence: bulk
> Reply-To: modproxy-dev@apache.org
> list-help:
> list-unsubscribe:
> list-post:
> Delivered-To: mailing list modproxy-dev@apache.org
> Received: (qmail 75563 invoked from network); 16 Jun 2003 16:14:32 -0000
> Message-ID: <3EEDECEA.5090104@snakefarm.org>
> Date: Mon, 16 Jun 2003 18:14:34 +0200
> From: Carsten Gaebler
> User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.3) Gecko/20030314
> X-Accept-Language: en-us, en
> MIME-Version: 1.0
> To: modproxy-dev@apache.org
> Subject: [PATCH] support for environment variables in ProxyPassReverse
> Content-Type: multipart/mixed;
> boundary="------------080307000004060702020300"
> X-Spam-Rating: daedalus.apache.org 1.6.2 0/1000/N
> X-Text-Classification: good_mail
> X-POPFile-Link:

> 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.

Re: [PATCH] support for environment variables in ProxyPassReverse

am 18.06.2003 16:34:27 von Carsten Gaebler

This is a multi-part message in MIME format.
--------------080608050303080003010804
Content-Type: text/plain; charset=us-ascii; format=flowed
Content-Transfer-Encoding: 7bit

Graham Leggett wrote:
> Carsten Gaebler wrote:
[patch for 1.3.27 to support env vars in ProxyPassReverse]
> Is it possible to create a patch for Apache v2.0?

It's attached. I encountered one problem with Apache 1.3.27 and mod_ssl:
you have to apply the mod_ssl patches (i.e. run configure) *before* the
proxy patch. Otherwise the mod_ssl proxy patches don't get applied and
any proxy rewrite rules using https fall back to http. Maybe this is
something that should be taken care of.

cg.

--------------080608050303080003010804
Content-Type: text/plain;
name="proxypassreverse-env-2.0.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
filename="proxypassreverse-env-2.0.patch"

--- proxy_http.c.orig Tue Apr 15 18:36:16 2003
+++ proxy_http.c Wed Jun 18 11:35:07 2003
@@ -145,11 +145,75 @@
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;
+ apr_array_header_t* result_array;
+
+ result_array = apr_array_make(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, 0, r->server,
+ "proxy: missing closing '}' in ENV expression: %s",
+ s);
+ return s;
+ }
+
+ var = apr_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 = apr_table_get(r->notes, var);
+ /* second try the internal Apache env structure */
+ if (value == NULL) {
+ value = apr_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, 0, r->server,
+ "proxy: environment variable %s is empty",
+ var);
+ }
+ }
+ }
+
+ *((const char **) apr_array_push(result_array)) =
+ apr_pstrndup(r->pool, p, var_start - p - 6);
+
+ *((const char **) apr_array_push(result_array)) = value;
+
+ p = var_end + 1;
+ }
+
+ if ((p != NULL) && (*p != '\0')) {
+ *((const char **) apr_array_push(result_array)) = p;
+ }
+
+ return apr_array_pstrcat(r->pool, result_array, '\0');
+}
+
static const char *ap_proxy_location_reverse_map(request_rec *r, proxy_server_conf *conf, const char *url)
{
struct proxy_alias *ent;
int i, l1, l2;
char *u;
+ const char* fake;
+ const char* real;

/* XXX FIXME: Make sure this handled the ambiguous case of the :80
* after the hostname */
@@ -157,9 +221,11 @@
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 = apr_pstrcat(r->pool, ent[i].fake, &url[l2], NULL);
+ fake = expand_vars(r, ent[i].fake);
+ real = expand_vars(r, ent[i].real);
+ l2 = strlen(real);
+ if (l1 >= l2 && strncmp(real, url, l2) == 0) {
+ u = apr_pstrcat(r->pool, fake, &url[l2], NULL);
return ap_construct_url(r->pool, u, r);
}
}

--------------080608050303080003010804--