diff -ur build-tree.orig/apache2/modules/proxy/mod_proxy.c build-tree/apache2/modules/proxy/mod_proxy.c
--- build-tree.orig/apache2/modules/proxy/mod_proxy.c	2005-02-04 21:21:18.000000000 +0100
+++ build-tree/apache2/modules/proxy/mod_proxy.c	2006-02-13 20:08:24.000000000 +0100
@@ -440,6 +440,10 @@
     ps->proxies = apr_array_make(p, 10, sizeof(struct proxy_remote));
     ps->aliases = apr_array_make(p, 10, sizeof(struct proxy_alias));
     ps->raliases = apr_array_make(p, 10, sizeof(struct proxy_alias));
+    ps->cookie_paths = apr_array_make(p, 10, sizeof(struct proxy_alias));
+    ps->cookie_domains = apr_array_make(p, 10, sizeof(struct proxy_alias));
+    ps->cookie_path_str = apr_strmatch_precompile(p, "path=", 0) ;
+    ps->cookie_domain_str = apr_strmatch_precompile(p, "domain=", 0) ;
     ps->noproxies = apr_array_make(p, 10, sizeof(struct noproxy_entry));
     ps->dirconn = apr_array_make(p, 10, sizeof(struct dirconn_entry));
     ps->allowed_connect_ports = apr_array_make(p, 10, sizeof(int));
@@ -475,6 +479,10 @@
     ps->sec_proxy = apr_array_append(p, base->sec_proxy, overrides->sec_proxy);
     ps->aliases = apr_array_append(p, base->aliases, overrides->aliases);
     ps->raliases = apr_array_append(p, base->raliases, overrides->raliases);
+    ps->cookie_paths = apr_array_append(p, base->cookie_paths, overrides->cookie_paths);
+    ps->cookie_domains = apr_array_append(p, base->cookie_domains, overrides->cookie_domains);
+    ps->cookie_path_str = base->cookie_path_str;
+    ps->cookie_domain_str = base->cookie_domain_str;
     ps->noproxies = apr_array_append(p, base->noproxies, overrides->noproxies);
     ps->dirconn = apr_array_append(p, base->dirconn, overrides->dirconn);
     ps->allowed_connect_ports = apr_array_append(p, base->allowed_connect_ports, overrides->allowed_connect_ports);
@@ -640,6 +648,37 @@
 
     return NULL;
 }
+static const char*
+    cookie_path(cmd_parms *cmd, void *dummy, const char *f, const char *r)
+{
+    server_rec *s = cmd->server;
+    proxy_server_conf *conf;
+    struct proxy_alias *new;
+
+    conf = (proxy_server_conf *)ap_get_module_config(s->module_config,
+                                                     &proxy_module);
+    new = apr_array_push(conf->cookie_paths) ;
+    new->fake = f;
+    new->real = r;
+    new->confpath=cmd->path;
+    return NULL ;
+}
+static const char*
+    cookie_domain(cmd_parms *cmd, void *dummy, const char *f, const char *r)
+{
+    server_rec *s = cmd->server;
+    proxy_server_conf *conf;
+    struct proxy_alias *new;
+
+    conf = (proxy_server_conf *)ap_get_module_config(s->module_config,
+                                                     &proxy_module);
+    new = apr_array_push(conf->cookie_domains) ;
+    new->fake = f;
+    new->real = r;
+    new->confpath=cmd->path;
+    return NULL ;
+}
+
 
 static const char *
     set_proxy_exclude(cmd_parms *parms, void *dummy, const char *arg)
@@ -1006,6 +1045,10 @@
      "a virtual path and a URL"),
     AP_INIT_TAKE12("ProxyPassReverse", add_pass_reverse, NULL, RSRC_CONF|ACCESS_CONF,
      "a virtual path and a URL for reverse proxy behaviour"),
+    AP_INIT_TAKE2("ProxyPassReverseCookiePath", cookie_path, NULL,
+	RSRC_CONF|ACCESS_CONF, "Path rewrite rule for proxying cookies") ,
+    AP_INIT_TAKE2("ProxyPassReverseCookieDomain", cookie_domain, NULL,
+	RSRC_CONF|ACCESS_CONF, "Domain rewrite rule for proxying cookies") ,
     AP_INIT_ITERATE("ProxyBlock", set_proxy_exclude, NULL, RSRC_CONF,
      "A list of names, hosts or domains to which the proxy will not connect"),
     AP_INIT_TAKE1("ProxyReceiveBufferSize", set_recv_buffer_size, NULL, RSRC_CONF,
diff -ur build-tree.orig/apache2/modules/proxy/mod_proxy.h build-tree/apache2/modules/proxy/mod_proxy.h
--- build-tree.orig/apache2/modules/proxy/mod_proxy.h	2005-02-04 21:21:18.000000000 +0100
+++ build-tree/apache2/modules/proxy/mod_proxy.h	2006-02-13 20:08:24.000000000 +0100
@@ -51,6 +51,7 @@
 #include "apr_uri.h"
 #include "apr_date.h"
 #include "apr_fnmatch.h"
+#include "apr_strmatch.h"
 #define APR_WANT_STRFUNC
 #include "apr_want.h"
 
@@ -101,6 +102,7 @@
 struct proxy_alias {
     const char *real;
     const char *fake;
+    const char *confpath;
 };
 
 struct dirconn_entry {
@@ -160,6 +162,15 @@
     } badopt;                   /* how to deal with bad headers */
     char badopt_set;
 
+/* new stuff on the end maximises binary back-compatibility.
+   the strmatch_patterns are really a const just to have a
+   case-independent strstr.
+ */
+  apr_array_header_t* cookie_paths ;
+  apr_array_header_t* cookie_domains ;
+  const apr_strmatch_pattern* cookie_path_str ;
+  const apr_strmatch_pattern* cookie_domain_str ;
+
 } proxy_server_conf;
 
 typedef struct {
diff -ur build-tree.orig/apache2/modules/proxy/proxy_http.c build-tree/apache2/modules/proxy/proxy_http.c
--- build-tree.orig/apache2/modules/proxy/proxy_http.c	2006-02-13 20:09:20.000000000 +0100
+++ build-tree/apache2/modules/proxy/proxy_http.c	2006-02-13 20:03:31.000000000 +0100
@@ -130,6 +130,120 @@
     }
     return url;
 }
+/* cookies are a bit trickier to match: we've got two substrings to worry
+ * about, and we can't just find them with strstr 'cos of case.  Regexp
+ * matching would be an easy fix, but for better consistency with all the
+ * other matches we'll refrain and use apr_strmatch to find path=/domain=
+ * and stick to plain strings for the config values.
+ */
+static const char *proxy_cookie_reverse_map(request_rec *r, proxy_server_conf *conf, const char *str)
+{
+    struct proxy_alias *ent;
+    size_t len = strlen(str);
+    const char* newpath = NULL ;
+    const char* newdomain = NULL ;
+    const char* pathp ;
+    const char* domainp ;
+    const char* pathe ;
+    const char* domaine ;
+    size_t l1, l2, i, poffs, doffs ;
+    int ddiff = 0 ;
+    int pdiff = 0 ;
+    char* ret ;
+
+/* find the match and replacement, but save replacing until we've done
+   both path and domain so we know the new strlen
+*/
+    if ( pathp = apr_strmatch(conf->cookie_path_str, str, len) , pathp ) {
+        pathp += 5 ;
+        poffs = pathp - str ;
+        pathe = strchr(pathp, ';') ;
+        l1 = pathe ? (pathe-pathp) : strlen(pathp) ;
+        pathe = pathp + l1 ;
+        ent = (struct proxy_alias *)conf->cookie_paths->elts;
+        for (i = 0; i < conf->cookie_paths->nelts; i++) {
+            l2 = strlen(ent[i].fake);
+            if (l1 >= l2 && strncmp(ent[i].fake, pathp, l2) == 0) {
+            	if (ent[i].confpath) {
+	            	ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,
+		                 "proxy: matched %s, location %s, uri %s %d", ent[i].fake, ent[i].confpath, r->uri);
+            		if (strncmp(ent[i].confpath, r->uri, strlen(ent[i].confpath)) == 0) {
+		            	ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,
+			                 "proxy: matched and uri, location match %s, location %s, uri %s", ent[i].fake, ent[i].confpath, r->uri);
+		                newpath = ent[i].real ;
+	    	            pdiff = strlen(newpath) - l1 ;
+	        	        break ;
+            		}
+            	} else {
+	            	ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,
+		                 "proxy: matched %s no location", ent[i].fake);
+	                newpath = ent[i].real ;
+    	            pdiff = strlen(newpath) - l1 ;
+        	        break ;
+        	    }
+            }
+        }
+    }
+    if ( domainp = apr_strmatch(conf->cookie_domain_str, str, len) , domainp ) {
+        domainp += 7 ;
+        doffs = domainp - str ;
+        domaine = strchr(domainp, ';') ;
+        l1 = domaine ? (domaine-domainp) : strlen(domainp) ;
+        domaine = domainp + l1 ;
+        ent = (struct proxy_alias *)conf->cookie_domains->elts;
+        for (i = 0; i < conf->cookie_domains->nelts; i++) {
+            l2 = strlen(ent[i].fake);
+            if (l1 >= l2 && strncmp(ent[i].fake, domainp, l2) == 0) {
+            	if (ent[i].confpath) {
+            		if (strncmp(ent[i].confpath, r->uri, strlen(ent[i].confpath)) == 0) {
+		                newdomain = ent[i].real ;
+		                ddiff = strlen(newdomain) - l1 ;
+		                break ;
+		            }
+		        } else {
+	                newdomain = ent[i].real ;
+	                ddiff = strlen(newdomain) - l1 ;
+	                break ;
+	            }
+            }
+        }
+    }
+    if ( newpath ) {
+        ret = apr_palloc(r->pool, len+pdiff+ddiff+1) ;
+        l1 = strlen(newpath) ;
+        if ( newdomain ) {
+            l2 = strlen(newdomain) ;
+            if ( doffs > poffs ) {
+                memcpy(ret, str, poffs) ;
+                memcpy(ret+poffs, newpath, l1) ;
+                memcpy(ret+poffs+l1, pathe, domainp-pathe) ;
+                memcpy(ret+doffs+pdiff, newdomain, l2) ;
+                strcpy(ret+doffs+pdiff+l2, domaine) ;
+            } else {
+                memcpy(ret, str, doffs) ;
+                memcpy(ret+doffs, newdomain, l2) ;
+                memcpy(ret+doffs+l2, domaine, pathp-domaine) ;
+                memcpy(ret+poffs+ddiff, newpath, l1) ;
+                strcpy(ret+poffs+ddiff+l1, pathe) ;
+            }
+        } else {
+            memcpy(ret, str, poffs) ;
+            memcpy(ret+poffs, newpath, l1) ;
+            strcpy(ret+poffs+l1, pathe) ;
+        }
+    } else {
+        if ( newdomain ) {
+            ret = apr_palloc(r->pool, len+pdiff+ddiff+1) ;
+            l2 = strlen(newdomain) ;
+            memcpy(ret, str, doffs) ;
+            memcpy(ret+doffs, newdomain, l2) ;
+            strcpy(ret+doffs+l2, domaine) ;
+        } else {
+            ret = (char*) str ;	/* no change */
+        }
+    }
+    return ret ;
+}
 
 /* Clear all connection-based headers from the incoming headers table */
 static void ap_proxy_clear_connection(apr_pool_t *p, apr_table_t *headers)
@@ -659,6 +773,42 @@
     return APR_SUCCESS;
 }
 
+typedef struct {
+  request_rec* r ;
+  proxy_server_conf* c ;
+} hdr_rec ;
+static int process_proxy_header(void* CTX, const char* key, const char* value) {
+    hdr_rec* ctx = CTX ;
+    static const char* date_hdrs[]
+        = { "Date", "Expires", "Last-Modified", NULL } ;
+    static const struct {
+        const char* name ;
+        const char* (*func)(request_rec*, proxy_server_conf*, const char*) ;
+    } transform_hdrs[] = {
+        { "Location", ap_proxy_location_reverse_map } ,
+        { "Content-Location", ap_proxy_location_reverse_map } ,
+        { "URI", ap_proxy_location_reverse_map } ,
+        { "Set-Cookie", proxy_cookie_reverse_map } ,
+        { NULL, NULL }
+    } ;
+    int i ;
+    for ( i = 0 ; date_hdrs[i] ; ++i ) {
+        if ( !strcasecmp(date_hdrs[i], key) ) {
+            apr_table_add(ctx->r->headers_out, key,
+                ap_proxy_date_canon(ctx->r->pool, value)) ;
+            return 1 ;
+        }
+    }
+    for ( i = 0 ; transform_hdrs[i].name ; ++i ) {
+        if ( !strcasecmp(transform_hdrs[i].name, key) ) {
+            apr_table_add(ctx->r->headers_out, key,
+                (*transform_hdrs[i].func)(ctx->r, ctx->c, value)) ;
+            return 2 ;
+       }
+    }
+    apr_table_add(ctx->r->headers_out, key, value) ;
+    return 3 ;
+}
 static
 apr_status_t ap_proxy_http_process_response(apr_pool_t * p, request_rec *r,
                                             proxy_http_conn_t *p_conn,
@@ -667,6 +817,7 @@
                                             proxy_server_conf *conf,
                                             apr_bucket_brigade *bb,
                                             char *server_portstr) {
+    apr_table_t* backend_headers ;
     conn_rec *c = r->connection;
     char buffer[HUGE_STRING_LEN];
     char keepchar;
@@ -678,6 +829,9 @@
                                 * in the case that the origin told us
                                 * to HTTP_CONTINUE
                                 */
+    hdr_rec hdrctx ;
+    hdrctx.r = r ;
+    hdrctx.c = conf ;
 
     /* Get response from the remote server, and pass it up the
      * filter chain
@@ -749,9 +903,9 @@
             /* N.B. for HTTP/1.0 clients, we have to fold line-wrapped headers*/
             /* Also, take care with headers with multiple occurences. */
 
-            r->headers_out = ap_proxy_read_headers(r, rp, buffer,
+            backend_headers = ap_proxy_read_headers(r, rp, buffer,
                                                    sizeof(buffer), origin);
-            if (r->headers_out == NULL) {
+            if (backend_headers == NULL) {
                 ap_log_error(APLOG_MARK, APLOG_WARNING, 0,
                              r->server, "proxy: bad HTTP/%d.%d header "
                              "returned by %s (%s)", major, minor, r->uri,
@@ -762,7 +916,7 @@
                  * are in a bad position here.. so force everything we send out
                  * to have nothing to do with the incoming packet
                  */
-                r->headers_out = apr_table_make(r->pool,1);
+                backend_headers = apr_table_make(r->pool,1);
                 r->status = HTTP_BAD_GATEWAY;
                 r->status_line = "bad gateway";
                 return r->status;
@@ -771,13 +925,13 @@
                 const char *buf;
 
                 /* can't have both Content-Length and Transfer-Encoding */
-                if (apr_table_get(r->headers_out, "Transfer-Encoding")
-                    && apr_table_get(r->headers_out, "Content-Length")) {
+                if (apr_table_get(backend_headers, "Transfer-Encoding")
+                    && apr_table_get(backend_headers, "Content-Length")) {
                     /* 2616 section 4.4, point 3: "if both Transfer-Encoding
                      * and Content-Length are received, the latter MUST be
                      * ignored"; so unset it here to prevent any confusion
                      * later. */
-                    apr_table_unset(r->headers_out, "Content-Length");
+                    apr_table_unset(backend_headers, "Content-Length");
                     ap_log_error(APLOG_MARK, APLOG_DEBUG, 0,
                                  r->server,
                                  "proxy: server %s returned Transfer-Encoding and Content-Length",
@@ -786,11 +940,11 @@
                 }
                 
                 /* strip connection listed hop-by-hop headers from response */
-                p_conn->close += ap_proxy_liststr(apr_table_get(r->headers_out,
+                p_conn->close += ap_proxy_liststr(apr_table_get(backend_headers,
                                                                 "Connection"),
                                                   "close");
-                ap_proxy_clear_connection(p, r->headers_out);
-                if ((buf = apr_table_get(r->headers_out, "Content-Type"))) {
+                ap_proxy_clear_connection(p, backend_headers);
+                if ((buf = apr_table_get(backend_headers, "Content-Type"))) {
                     ap_set_content_type(r, apr_pstrdup(p, buf));
                 }            
                 ap_proxy_pre_http_request(origin,rp);
@@ -799,7 +953,7 @@
             /* handle Via header in response */
             if (conf->viaopt != via_off && conf->viaopt != via_block) {
                 /* create a "Via:" response header entry and merge it */
-                apr_table_mergen(r->headers_out, "Via",
+                apr_table_mergen(backend_headers, "Via",
                                  (conf->viaopt == via_full)
                                      ? apr_psprintf(p, "%d.%d %s%s (%s)",
                                            HTTP_VERSION_MAJOR(r->proto_num),
@@ -835,41 +989,17 @@
                          "proxy: HTTP: received 100 CONTINUE");
         }
 
-        /* we must accept 3 kinds of date, but generate only 1 kind of date */
-        {
-            const char *buf;
-            if ((buf = apr_table_get(r->headers_out, "Date")) != NULL) {
-                apr_table_set(r->headers_out, "Date",
-                              ap_proxy_date_canon(p, buf));
-            }
-            if ((buf = apr_table_get(r->headers_out, "Expires")) != NULL) {
-                apr_table_set(r->headers_out, "Expires",
-                              ap_proxy_date_canon(p, buf));
-            }
-            if ((buf = apr_table_get(r->headers_out, "Last-Modified")) != NULL) {
-                apr_table_set(r->headers_out, "Last-Modified",
-                              ap_proxy_date_canon(p, buf));
-            }
-        }
-
-        /* munge the Location and URI response headers according to
-         * ProxyPassReverse
-         */
-        {
-            const char *buf;
-            if ((buf = apr_table_get(r->headers_out, "Location")) != NULL) {
-                apr_table_set(r->headers_out, "Location",
-                              ap_proxy_location_reverse_map(r, conf, buf));
-            }
-            if ((buf = apr_table_get(r->headers_out, "Content-Location")) != NULL) {
-                apr_table_set(r->headers_out, "Content-Location",
-                              ap_proxy_location_reverse_map(r, conf, buf));
-            }
-            if ((buf = apr_table_get(r->headers_out, "URI")) != NULL) {
-                apr_table_set(r->headers_out, "URI",
-                              ap_proxy_location_reverse_map(r, conf, buf));
-            }
+/* transcribe backend headers to headers_out, rewriting any that need it.
+ * The old method based on if ( apr_table_get(...) ) fails against
+ * duplicated headers, so we copy-and-transcribe by the entry instead.
+ */
+        if ( r->headers_out ) {
+            apr_table_clear(r->headers_out) ;
+        } else {
+            r->headers_out = apr_table_make(r->pool, 10) ;
         }
+        apr_table_do(process_proxy_header, &hdrctx, backend_headers, NULL) ;
+        apr_table_clear(backend_headers) ;
 
         if ((r->status == 401) && (conf->error_override != 0)) {
             const char *buf;
