Apache Patch: Pass environment variables to backends connected via mod_proxy_ajp

One popular method to connect Tomcat or JBoss to the Apache web server is using mod_proxy_ajp. This of course works very well except for the case where you want to pass some environment variables to the backends. This is especially true for those who want to implement a 404 error handler using Java or other languages backed by Java. A common request is to be able to pass the values of the REQUEST_… variables defined by Apache to the error handler. While the AJP13 protocol would actually allow for that to happen, mod_proxy_ajp doesn’t offer that functionality. Luckily it’s quite easy to patch the functionality in. All you need is the Apache source code. Download and unpack, then open the file modules/proxy/ajp_header.c in your favorite text editor. Look for this code snippet:

{openx:6}

for (i = 0; i < (apr_uint32_t)arr->nelts; i++) {
    if (!strncmp(elts[i].key, "AJP_", 4)) {
        if (ajp_msg_append_uint8(msg, SC_A_REQ_ATTRIBUTE) ||
            ajp_msg_append_string(msg, elts[i].key + 4)   ||
            ajp_msg_append_string(msg, elts[i].val)) {
            ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server,
                    "ajp_marshal_into_msgb: "
                     "Error appending attribute %s=%s",
                     elts[i].key, elts[i].val);
             return AJP_EOVERFLOW;
        }
    }
}

As one can see, this code walks the list of environment variables, picking those that start with “AJP_” and forwards them to the backend as an AJP header attribute. To do the same for the REQUEST_… variables we just have to extend that a bit:

for (i = 0; i < (apr_uint32_t)arr->nelts; i++) {
    if (!strncmp(elts[i].key, "AJP_", 4)) {
        /* ... code removed for brevity ... */
    } else if (!strncmp(elts[i].key, "REDIRECT_", 9)) {
         if (ajp_msg_append_uint8(msg, SC_A_REQ_ATTRIBUTE) ||
            ajp_msg_append_string(msg, elts[i].key)       ||
            ajp_msg_append_string(msg, elts[i].val)) {
            ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server,
                    "ajp_marshal_into_msgb: "
                    "Error appending attribute %s=%s",
                    elts[i].key, elts[i].val);
            return AJP_EOVERFLOW;
        }
    }
}

I know that there’s quite a bit of duplicate code in there but this way the code is easier to read and also executes fast than it would if we’d extended the initial if (…) clause. Also it just passes the REDIRECT_… variables for that’s all I needed. Should be easy to extend to different needs.

There’s one catch. To quote the official Tomcat documentation: You can retrieve the variables on Tomcat as request attributes via request.getAttribute(attributeName). Note that the variables sent as attributes will not be listed in request.getAttributeNames().

{openx:6}