Download | Plain Text | Line Numbers


diff --git a/docs/manual/mod/mod_proxy_fcgi.xml b/docs/manual/mod/mod_proxy_fcgi.xml
index fb3c7f8..c9f5941 100644
--- a/docs/manual/mod/mod_proxy_fcgi.xml
+++ b/docs/manual/mod/mod_proxy_fcgi.xml
@@ -119,4 +119,33 @@ ProxyPass /myapp/ balancer://myappcluster/
     </dl>
 </section>
 
+<directivesynopsis>
+  <name>ProxyFCGIPassHeader</name>
+  <description>Header name which will be passed to FastCGI as environment variable.</description>
+  <syntax>ProxyFCGIPassHeader <em>name</em></syntax>
+  <default>none</default>
+  <contextlist><context>server config</context> <context>virtual host</context></contextlist>
+  <usage>
+    <p>This directive specifies the name of a request header which
+    will be passed to the FastCGI application as an environment
+    variable.  The name of the environment variable is derived from
+    the value specified on this directive, as discussed below:</p>
+
+    <p>The value specified on this directive is converted to
+    upper case, prefixed with <code>HTTP_</code>, and hyphens are
+    converted to underscores.</p>
+
+    <note type="hint"><title>Note</title>
+    <p>Most request headers are already available to the application
+    as environment variables, and generally are prefixed with
+    <code>HTTP_</code>.  (Notable exceptions are <code>Content-type</code>
+    and <code>Content-length</code>, which do not have the
+    <code>HTTP_</code> prefix.)  Thus, this directive is only required
+    for request headers that are purposefully omitted, such as
+    <code>Authorization</code> and <code>Proxy-Authorization</code>.
+    Only pass these request headers if absolutely required.</p>
+    </note>
+  </usage>
+</directivesynopsis>
+
 </modulesynopsis>
diff --git a/modules/proxy/mod_proxy_fcgi.c b/modules/proxy/mod_proxy_fcgi.c
index d7ab5cb..61447a6 100644
--- a/modules/proxy/mod_proxy_fcgi.c
+++ b/modules/proxy/mod_proxy_fcgi.c
@@ -20,6 +20,10 @@
 
 module AP_MODULE_DECLARE_DATA proxy_fcgi_module;
 
+typedef struct {
+    apr_array_header_t *pass_headers;
+} fcgi_server_conf;
+
 /*
  * Canonicalise http-like URLs.
  * scheme is the scheme for the URL
@@ -193,6 +197,62 @@ static apr_status_t send_begin_request(proxy_conn_rec *conn,
     return send_data(conn, vec, 2, &len);
 }
 
+/* http2env stolen from util_script.c */
+static char *http2env(request_rec *r, const char *w)
+{
+    char *res = (char *)apr_palloc(r->pool, sizeof("HTTP_") + strlen(w));
+    char *cp = res;
+    char c;
+
+    *cp++ = 'H';
+    *cp++ = 'T';
+    *cp++ = 'T';
+    *cp++ = 'P';
+    *cp++ = '_';
+
+    while ((c = *w++) != 0) {
+        if (apr_isalnum(c)) {
+            *cp++ = apr_toupper(c);
+        }
+        else if (c == '-') {
+            *cp++ = '_';
+        }
+        else {
+            if (APLOGrtrace1(r))
+                ap_log_rerror(APLOG_MARK, APLOG_TRACE1, 0, r,
+                            "Not exporting header with invalid name as envvar: %s",
+                            ap_escape_logitem(r->pool, w));
+            return NULL;
+        }
+    }
+    *cp = 0;
+
+    return res;
+}
+
+static void fcgi_add_cgi_vars(request_rec * r)
+{
+    fcgi_server_conf *conf =
+        ap_get_module_config(r->server->module_config, &proxy_fcgi_module);
+    apr_array_header_t *passheaders = conf->pass_headers;
+
+    if (passheaders != NULL) {
+        const char **hdr = (const char **) passheaders->elts;
+        int hdrcnt = passheaders->nelts;
+        int i;
+
+        for (i = 0; i < hdrcnt; i++, ++hdr) {
+            /* standard munging of header name (upcase, HTTP_, etc.) */
+            const char *name = http2env(r, *hdr);
+            const char *val = apr_table_get(r->headers_in, *hdr);
+
+            if (name && val) {
+                apr_table_setn(r->subprocess_env, name, val);
+            }
+        }
+    }
+}
+
 static apr_status_t send_environment(proxy_conn_rec *conn, request_rec *r,
                                      apr_pool_t *temp_pool,
                                      apr_uint16_t request_id)
@@ -209,6 +269,7 @@ static apr_status_t send_environment(proxy_conn_rec *conn, request_rec *r,
 
     ap_add_common_vars(r);
     ap_add_cgi_vars(r);
+    fcgi_add_cgi_vars(r);
 
     /* XXX are there any FastCGI specific env vars we need to send? */
 
@@ -840,6 +901,46 @@ cleanup:
     return status;
 }
 
+static void *create_config(apr_pool_t *p, server_rec *s)
+{
+    fcgi_server_conf *conf = apr_palloc(p, sizeof(*conf));
+    conf->pass_headers = apr_array_make(p, 10, sizeof(const char *));
+    return conf;
+}
+
+static void *merge_config(apr_pool_t *p, void *base_, void *add_)
+{
+    fcgi_server_conf *base = (fcgi_server_conf *)base_;
+    fcgi_server_conf *add  = (fcgi_server_conf *)add_;
+    fcgi_server_conf *conf = apr_pcalloc(p, sizeof(*conf));
+
+    conf->pass_headers = apr_array_append(p, base->pass_headers,
+                                          add->pass_headers);
+
+    return conf;
+}
+
+static const char *add_pass_headers(cmd_parms * cmd, void *dummy,
+                                   const char *arg)
+{
+    const char **header;
+    fcgi_server_conf *conf =
+        ap_get_module_config(cmd->server->module_config, &proxy_fcgi_module);
+
+    header = (const char **) apr_array_push(conf->pass_headers);
+    *header = ap_getword_conf(cmd->pool, &arg);
+
+    return header ? NULL : "Invalid ProxyFCGIPassHeader";
+}
+
+static const command_rec fcgi_cmds[] =
+{
+    AP_INIT_TAKE1("ProxyFCGIPassHeader", add_pass_headers,
+                  NULL, RSRC_CONF,
+                  "Header name which will be passed to FastCGI as environment variable."),
+    {NULL}
+};
+
 static void register_hooks(apr_pool_t *p)
 {
     proxy_hook_scheme_handler(proxy_fcgi_handler, NULL, NULL, APR_HOOK_FIRST);
@@ -850,8 +951,8 @@ AP_DECLARE_MODULE(proxy_fcgi) = {
     STANDARD20_MODULE_STUFF,
     NULL,                       /* create per-directory config structure */
     NULL,                       /* merge per-directory config structures */
-    NULL,                       /* create per-server config structure */
-    NULL,                       /* merge per-server config structures */
-    NULL,                       /* command apr_table_t */
+    create_config,              /* create per-server config structure */
+    merge_config,               /* merge per-server config structures */
+    fcgi_cmds,                  /* command apr_table_t */
     register_hooks              /* register hooks */
 };