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 */
};