From 23bad0a3298dc62f78ea4dac9d71015d41bfc0bb Mon Sep 17 00:00:00 2001 From: Graham Leggett Date: Thu, 21 Feb 2002 06:06:31 +0000 Subject: [PATCH] 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. 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 | 11 +++++++++++ modules/proxy/proxy_http.c | 10 +++++++--- modules/proxy/proxy_util.c | 32 +++++++++++++++++++++++++++++++- 3 files changed, 49 insertions(+), 4 deletions(-) diff --git a/CHANGES b/CHANGES index 8f74b24a36..4efe28373e 100644 --- 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 ] diff --git a/modules/proxy/proxy_http.c b/modules/proxy/proxy_http.c index d2bab6cbb0..d612d21cc1 100644 --- a/modules/proxy/proxy_http.c +++ b/modules/proxy/proxy_http.c @@ -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) { diff --git a/modules/proxy/proxy_util.c b/modules/proxy/proxy_util.c index 91ff75c0a8..37c65fd213 100644 --- a/modules/proxy/proxy_util.c +++ b/modules/proxy/proxy_util.c @@ -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); +} -- 2.50.1