Patch for: http://trac.lighttpd.net/trac/ticket/1545 Allows the headers to be used by mod_extforward to be specified in config. For example for use with a Zeus ZXTM loadbalancer: extforward.headers = ("X-Cluster-Client-Ip") diff -Nur ../lighttpd-1.4.18-original/src/mod_extforward.c ./src/mod_extforward.c --- ../lighttpd-1.4.18-original/src/mod_extforward.c 2007-08-18 11:43:35.000000000 +0200 +++ ./src/mod_extforward.c 2007-12-21 15:09:35.000000000 +0100 @@ -75,6 +75,7 @@ typedef struct { array *forwarder; + array *headers; } plugin_config; typedef struct { @@ -130,6 +131,7 @@ if (!s) continue; array_free(s->forwarder); + array_free(s->headers); free(s); } @@ -149,7 +151,8 @@ size_t i = 0; config_values_t cv[] = { - { "extforward.forwarder", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 0 */ + { "extforward.forwarder", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 0 */ + { "extforward.headers", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 1 */ { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET } }; @@ -161,9 +164,11 @@ plugin_config *s; s = calloc(1, sizeof(plugin_config)); - s->forwarder = array_init(); + s->forwarder = array_init(); + s->headers = array_init(); cv[0].destination = s->forwarder; + cv[1].destination = s->headers; p->config_storage[i] = s; @@ -182,6 +187,7 @@ plugin_config *s = p->config_storage[0]; PATCH(forwarder); + PATCH(headers); /* skip the first, the global context */ for (i = 1; i < srv->config_context->used; i++) { @@ -197,6 +203,8 @@ if (buffer_is_equal_string(du->key, CONST_STR_LEN("extforward.forwarder"))) { PATCH(forwarder); + } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("extforward.headers"))) { + PATCH(headers); } } } @@ -311,6 +319,8 @@ URIHANDLER_FUNC(mod_extforward_uri_handler) { plugin_data *p = p_d; data_string *forwarded = NULL; + data_string *ds; + size_t k; #ifdef HAVE_IPV6 char b2[INET6_ADDRSTRLEN + 1]; struct addrinfo *addrlist = NULL; @@ -322,6 +332,8 @@ #ifdef HAVE_IPV6 #endif + + if (!con->request.headers) return HANDLER_GO_ON; mod_extforward_patch_connection(srv, con, p); @@ -331,6 +343,34 @@ "-- mod_extforward_uri_handler called"); } +/*************************************************************************************************/ + // p->conf.headers + forwarded = NULL; + for(k=0; kconf.headers->used; k++) { + ds = (data_string *)p->conf.headers->data[k]; + + forwarded = (data_string*)array_get_element(con->request.headers, ds->value->ptr); + if(NULL != forwarded) { + break; + } + } + + if(NULL == forwarded) { + if ((NULL == (forwarded = (data_string *) array_get_element(con->request.headers,"X-Forwarded-For")) && + NULL == (forwarded = (data_string *) array_get_element(con->request.headers, "Forwarded-For"))) || + (p->conf.headers->used > 0)) { + + if (con->conf.log_request_handling) { + log_error_write(srv, __FILE__, __LINE__, "s", "no forward header found, skipping"); + } + + return HANDLER_GO_ON; + } + } + +/*************************************************************************************************/ + +/* if ((NULL == (forwarded = (data_string *) array_get_element(con->request.headers,"X-Forwarded-For")) && NULL == (forwarded = (data_string *) array_get_element(con->request.headers, "Forwarded-For")))) { @@ -341,7 +381,7 @@ return HANDLER_GO_ON; } - +*/ /* if the remote ip itself is not trusted , then do nothing */ #ifdef HAVE_IPV6 dst_addr_str = inet_ntop(con->dst_addr.plain.sa_family, @@ -367,7 +407,7 @@ /* Testing shows that multiple headers and multiple values in one header come in _reverse_ order. So the first one we get is the last one in the request. */ for (i = forward_array->used - 1; i >= 0; i--) { - data_string *ds = (data_string *) forward_array->data[i]; + ds = (data_string *) forward_array->data[i]; if (ds) { real_remote_addr = ds->value->ptr; break; diff -Nur ../lighttpd-1.4.18-original/src/response.c ./src/response.c --- ../lighttpd-1.4.18-original/src/response.c 2007-04-13 22:47:40.000000000 +0200 +++ ./src/response.c 2007-12-31 15:22:56.000000000 +0100 @@ -137,6 +137,11 @@ if (con->mode == DIRECT && con->physical.path->used == 0) { char *qstr; + size_t i; + for(i = 0; i < COMP_LAST_ELEMENT; ++i) { + con->conditional_is_valid[i] = 0; + } + /* we only come here when we have the parse the full request again * * a HANDLER_COMEBACK from mod_rewrite and mod_fastcgi might be a