]> granicus.if.org Git - apache/commitdiff
Some browsers ignore cookies that have been merged into a
authorGraham Leggett <minfrin@apache.org>
Thu, 21 Feb 2002 06:06:31 +0000 (06:06 +0000)
committerGraham Leggett <minfrin@apache.org>
Thu, 21 Feb 2002 06:06:31 +0000 (06:06 +0000)
single Set-Cookie header. Set-Cookie and Set-Cookie2 headers
are now unmerged in the http proxy before being sent to the
client.
Fix a problem with proxy where each entry of a duplicated
header such as Set-Cookie would overwrite and obliterate the
previous value of the header, resulting in multiple header
values (like cookies) going missing.
PR:
Obtained from:
Submitted by:
Reviewed by:

git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@93527 13f79535-47bb-0310-9956-ffa450edef68

CHANGES
modules/proxy/proxy_http.c
modules/proxy/proxy_util.c

diff --git a/CHANGES b/CHANGES
index 8f74b24a363ac975ff905b6d2509fc1170c13edd..4efe28373eee4a03af9bd88881475883ff231fe2 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,5 +1,16 @@
 Changes with Apache 2.0.33-dev
 
+  *) Some browsers ignore cookies that have been merged into a
+     single Set-Cookie header. Set-Cookie and Set-Cookie2 headers
+     are now unmerged in the http proxy before being sent to the
+     client. [Graham Leggett]
+
+  *) Fix a problem with proxy where each entry of a duplicated
+     header such as Set-Cookie would overwrite and obliterate the
+     previous value of the header, resulting in multiple header
+     values (like cookies) going missing.
+     [Graham Leggett, Joshua Slive]
+
   *) Add the server-limit and thread-limit values to the scoreboard
      for the sake of third-party applications.
      [Adam Sussman <myddryn@vishnu.vidya.com>]
index d2bab6cbb0d6ae522e5f8ad11f31c778bfa5a528..d612d21cc1894afed3e2eef0241d0b7b9607a555 100644 (file)
@@ -569,21 +569,21 @@ apr_status_t ap_proxy_http_request(apr_pool_t *p, request_rec *r,
         /* Add X-Forwarded-For: so that the upstream has a chance to
          * determine, where the original request came from.
          */
-        apr_table_setn(r->headers_in, "X-Forwarded-For",
+        apr_table_mergen(r->headers_in, "X-Forwarded-For",
                        r->connection->remote_ip);
 
         /* Add X-Forwarded-Host: so that upstream knows what the
          * original request hostname was.
          */
         if ((buf = apr_table_get(r->headers_in, "Host"))) {
-            apr_table_setn(r->headers_in, "X-Forwarded-Host", buf);
+            apr_table_mergen(r->headers_in, "X-Forwarded-Host", buf);
         }
 
         /* Add X-Forwarded-Server: so that upstream knows what the
          * name of this proxy server is (if there are more than one)
          * XXX: This duplicates Via: - do we strictly need it?
          */
-        apr_table_setn(r->headers_in, "X-Forwarded-Server",
+        apr_table_mergen(r->headers_in, "X-Forwarded-Server",
                        r->server->server_hostname);
     }
 
@@ -835,6 +835,10 @@ apr_status_t ap_proxy_http_process_response(apr_pool_t * p, request_rec *r,
             }
         }
 
+        /* cookies are special: they must not be merged (stupid browsers) */
+        ap_proxy_table_unmerge(r->pool, r->headers_out, "Set-Cookie");
+        ap_proxy_table_unmerge(r->pool, r->headers_out, "Set-Cookie2");
+
         r->sent_bodyct = 1;
         /* Is it an HTTP/0.9 response? If so, send the extra data */
         if (backasswards) {
index 91ff75c0a8ef0c2c6a47274bd84ecf83b90cc837..37c65fd2138e86fa98740e496ebb87c423797a52 100644 (file)
@@ -439,7 +439,8 @@ PROXY_DECLARE(apr_table_t *)ap_proxy_read_headers(request_rec *r, request_rec *r
        for (end = &value[strlen(value)-1]; end > value && apr_isspace(*end); --end)
            *end = '\0';
 
-        apr_table_add(headers_out, buffer, value);
+        /* make sure we merge so as not to destroy duplicated headers */
+        apr_table_merge(headers_out, buffer, value);
 
        /* the header was too long; at the least we should skip extra data */
        if (len >= size - 1) { 
@@ -1071,3 +1072,32 @@ PROXY_DECLARE(void) ap_proxy_reset_output_filters(conn_rec *c)
         }
     }
 }
+
+/* unmerge an element in the table */
+void ap_proxy_table_unmerge(apr_pool_t *p, apr_table_t *t, char *key)
+{
+    apr_off_t offset = 0;
+    apr_off_t count = 0;
+    char *value = NULL;
+
+    /* get the value to unmerge */
+    const char *initial = apr_table_get(t, key);
+    if (!initial) {
+        return;
+    }
+    value = apr_pstrdup(p, initial);
+
+    /* remove the value from the headers */
+    apr_table_unset(t, key);
+
+    /* find each comma */
+    while (value[count]) {
+        if (value[count] == ',') {
+            value[count] = 0;
+            apr_table_add(t, key, value + offset);
+            offset = count + 1;
+        }
+        count++;
+    }
+    apr_table_add(t, key, value + offset);
+}