#define Curl_checkProxyheaders(x,y,z,a) NULL
#endif
+static bool http_header_is_empty(const char *header)
+{
+ struct Curl_str out;
+
+ if(!curlx_str_cspn(&header, &out, ";:") &&
+ (!curlx_str_single(&header, ':') || !curlx_str_single(&header, ';'))) {
+ curlx_str_untilnl(&header, &out, MAX_HTTP_RESP_HEADER_SIZE);
+ curlx_str_trimblanks(&out);
+ return curlx_strlen(&out) == 0;
+ }
+ return TRUE; /* invalid head format, treat as empty */
+}
+
/*
* Strip off leading and trailing whitespace from the value in the given HTTP
* header line and return a strdup()ed copy. Returns NULL in case of
curlx_str_casecompare(&name, "Content-Length"))
;
else if(curlx_str_casecompare(&name, "Connection"))
- /* Normal Connection: header generation takes care of this */
+ /* Connection headers are handled specially */
;
else if((httpversion >= 20) &&
curlx_str_casecompare(&name, "Transfer-Encoding"))
static CURLcode http_add_connection_hd(struct Curl_easy *data,
struct dynbuf *req)
{
- char *custom = Curl_checkheaders(data, STRCONST("Connection"));
- char *custom_val = custom ? Curl_copy_header_value(custom) : NULL;
- const char *sep = (custom_val && *custom_val) ? ", " : "Connection: ";
+ struct curl_slist *head;
+ const char *sep = "Connection: ";
CURLcode result = CURLE_OK;
size_t rlen = curlx_dyn_len(req);
+ char *value;
+ bool skip;
+
+ /* Add the 1st custom "Connection: " header, if there is one */
+ for(head = data->set.headers; head; head = head->next) {
+ if(curl_strnequal(head->data, "Connection", 10) &&
+ Curl_headersep(head->data[10]) &&
+ !http_header_is_empty(head->data)) {
+ value = Curl_copy_header_value(head->data);
+ if(!value)
+ return CURLE_OUT_OF_MEMORY;
+ result = curlx_dyn_addf(req, "%s%s", sep, value);
+ sep = ", ";
+ free(value);
+ break; /* leave, having added 1st one */
+ }
+ }
- if(custom && !custom_val)
- return CURLE_OUT_OF_MEMORY;
-
- if(custom_val && *custom_val)
- result = curlx_dyn_addf(req, "Connection: %s", custom_val);
+ /* add our internal Connection: header values, if we have any */
if(!result && data->state.http_hd_te) {
result = curlx_dyn_addf(req, "%s%s", sep, "TE");
sep = ", ";
}
if(!result && (rlen < curlx_dyn_len(req)))
result = curlx_dyn_addn(req, STRCONST("\r\n"));
+ if(result)
+ return result;
- free(custom_val);
- return result;
+ /* Add all user-defined Connection: headers after the first */
+ skip = TRUE;
+ for(head = data->set.headers; head; head = head->next) {
+ if(curl_strnequal(head->data, "Connection", 10) &&
+ Curl_headersep(head->data[10]) &&
+ !http_header_is_empty(head->data)) {
+ if(skip) {
+ skip = FALSE;
+ continue;
+ }
+ result = curlx_dyn_addf(req, "%s\r\n", head->data);
+ if(result)
+ return result;
+ }
+ }
+
+ return CURLE_OK;
}
/* Header identifier in order we send them by default */
--- /dev/null
+<testcase>
+<info>
+<keywords>
+HTTP
+HTTP GET
+compressed
+Transfer-Encoding
+</keywords>
+</info>
+#
+# Server-side
+<reply>
+<data>
+HTTP/1.1 200 OK\r
+Date: Mon, 29 Nov 2004 21:56:53 GMT\r
+Server: Apache/1.3.31 (Debian GNU/Linux) mod_gzip/1.3.26.1a PHP/4.3.9-1 mod_ssl/2.8.20 OpenSSL/0.9.7d mod_perl/1.29\r
+Vary: Accept-Encoding\r
+Content-Type: text/html; charset=ISO-8859-1\r
+Transfer-Encoding: gzip, chunked\r
+\r
+2c\r
+%hex[%1f%8b%08%08%79%9e%ab%41%00%03%6c%61%6c%61%6c%61%00%cb%c9%cc%4b%55%30%e4%52%c8%01%d1%46%5c]hex%
+%hex[%10%86%31%17%00]hex%
+%hex[%02%71%60%18%00%00%00]hex%\r
+0\r
+\r
+</data>
+
+<datacheck>
+HTTP/1.1 200 OK\r
+Date: Mon, 29 Nov 2004 21:56:53 GMT\r
+Server: Apache/1.3.31 (Debian GNU/Linux) mod_gzip/1.3.26.1a PHP/4.3.9-1 mod_ssl/2.8.20 OpenSSL/0.9.7d mod_perl/1.29\r
+Vary: Accept-Encoding\r
+Content-Type: text/html; charset=ISO-8859-1\r
+Transfer-Encoding: gzip, chunked\r
+\r
+line 1
+ line 2
+ line 3
+</datacheck>
+
+</reply>
+
+#
+# Client-side
+<client>
+<features>
+libz
+</features>
+<server>
+http
+</server>
+<name>
+HTTP GET transfer-encoding with two user Connection: headers
+</name>
+<command>
+http://%HOSTIP:%HTTPPORT/%TESTNUMBER --tr-encoding -H "Connection: this" -H "Connection: that"
+</command>
+</client>
+
+#
+# Verify data after the test has been "shot"
+<verify>
+<protocol>
+GET /%TESTNUMBER HTTP/1.1\r
+Host: %HOSTIP:%HTTPPORT\r
+User-Agent: curl/%VERSION\r
+Accept: */*\r
+TE: gzip\r
+Connection: this, TE\r
+Connection: that\r
+\r
+</protocol>
+</verify>
+</testcase>